@zzzen/pyright-internal 1.2.0-dev.20230423 → 1.2.0-dev.20230430

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 (166) hide show
  1. package/dist/analyzer/analyzerFileInfo.d.ts +4 -1
  2. package/dist/analyzer/analyzerFileInfo.js.map +1 -1
  3. package/dist/analyzer/backgroundAnalysisProgram.d.ts +4 -4
  4. package/dist/analyzer/backgroundAnalysisProgram.js +10 -7
  5. package/dist/analyzer/backgroundAnalysisProgram.js.map +1 -1
  6. package/dist/analyzer/binder.js +12 -7
  7. package/dist/analyzer/binder.js.map +1 -1
  8. package/dist/analyzer/checker.js +6 -3
  9. package/dist/analyzer/checker.js.map +1 -1
  10. package/dist/analyzer/dataClasses.js +5 -2
  11. package/dist/analyzer/dataClasses.js.map +1 -1
  12. package/dist/analyzer/declarationUtils.d.ts +6 -1
  13. package/dist/analyzer/declarationUtils.js +10 -8
  14. package/dist/analyzer/declarationUtils.js.map +1 -1
  15. package/dist/analyzer/importResolver.d.ts +15 -15
  16. package/dist/analyzer/importResolver.js +477 -477
  17. package/dist/analyzer/importResolver.js.map +1 -1
  18. package/dist/analyzer/namedTuples.d.ts +1 -1
  19. package/dist/analyzer/namedTuples.js +29 -41
  20. package/dist/analyzer/namedTuples.js.map +1 -1
  21. package/dist/analyzer/packageTypeReport.d.ts +2 -1
  22. package/dist/analyzer/packageTypeReport.js +2 -1
  23. package/dist/analyzer/packageTypeReport.js.map +1 -1
  24. package/dist/analyzer/packageTypeVerifier.d.ts +1 -1
  25. package/dist/analyzer/packageTypeVerifier.js +27 -13
  26. package/dist/analyzer/packageTypeVerifier.js.map +1 -1
  27. package/dist/analyzer/program.d.ts +25 -37
  28. package/dist/analyzer/program.js +1356 -1508
  29. package/dist/analyzer/program.js.map +1 -1
  30. package/dist/analyzer/protocols.js +1 -1
  31. package/dist/analyzer/protocols.js.map +1 -1
  32. package/dist/analyzer/service.d.ts +12 -25
  33. package/dist/analyzer/service.js +76 -109
  34. package/dist/analyzer/service.js.map +1 -1
  35. package/dist/analyzer/sourceFile.d.ts +6 -18
  36. package/dist/analyzer/sourceFile.js +57 -121
  37. package/dist/analyzer/sourceFile.js.map +1 -1
  38. package/dist/analyzer/sourceFileInfoUtils.d.ts +7 -1
  39. package/dist/analyzer/sourceFileInfoUtils.js.map +1 -1
  40. package/dist/analyzer/typeEvaluator.js +354 -322
  41. package/dist/analyzer/typeEvaluator.js.map +1 -1
  42. package/dist/analyzer/typeEvaluatorTypes.d.ts +6 -2
  43. package/dist/analyzer/typeGuards.js +3 -1
  44. package/dist/analyzer/typeGuards.js.map +1 -1
  45. package/dist/analyzer/typeStubWriter.js.map +1 -1
  46. package/dist/analyzer/typeUtils.d.ts +1 -0
  47. package/dist/analyzer/typeUtils.js +35 -8
  48. package/dist/analyzer/typeUtils.js.map +1 -1
  49. package/dist/backgroundAnalysisBase.d.ts +10 -11
  50. package/dist/backgroundAnalysisBase.js +87 -87
  51. package/dist/backgroundAnalysisBase.js.map +1 -1
  52. package/dist/commands/dumpFileDebugInfoCommand.js +8 -8
  53. package/dist/commands/dumpFileDebugInfoCommand.js.map +1 -1
  54. package/dist/commands/quickActionCommand.js +4 -1
  55. package/dist/commands/quickActionCommand.js.map +1 -1
  56. package/dist/common/cancellationUtils.d.ts +1 -1
  57. package/dist/common/cancellationUtils.js +9 -9
  58. package/dist/common/cancellationUtils.js.map +1 -1
  59. package/dist/common/commandLineOptions.d.ts +1 -2
  60. package/dist/common/commandLineOptions.js.map +1 -1
  61. package/dist/common/configOptions.d.ts +2 -2
  62. package/dist/common/configOptions.js.map +1 -1
  63. package/dist/common/console.d.ts +5 -9
  64. package/dist/common/console.js +46 -33
  65. package/dist/common/console.js.map +1 -1
  66. package/dist/common/deferred.js +10 -10
  67. package/dist/common/deferred.js.map +1 -1
  68. package/dist/common/extensibility.d.ts +26 -5
  69. package/dist/common/extensibility.js +1 -1
  70. package/dist/common/extensibility.js.map +1 -1
  71. package/dist/common/fileBasedCancellationUtils.js +5 -5
  72. package/dist/common/fileBasedCancellationUtils.js.map +1 -1
  73. package/dist/common/fileSystem.d.ts +12 -10
  74. package/dist/common/fileSystem.js.map +1 -1
  75. package/dist/common/fullAccessHost.d.ts +3 -3
  76. package/dist/common/fullAccessHost.js +6 -6
  77. package/dist/common/fullAccessHost.js.map +1 -1
  78. package/dist/common/pathUtils.d.ts +2 -2
  79. package/dist/common/pathUtils.js.map +1 -1
  80. package/dist/common/realFileSystem.js +12 -7
  81. package/dist/common/realFileSystem.js.map +1 -1
  82. package/dist/common/uriParser.d.ts +2 -2
  83. package/dist/common/uriParser.js +3 -3
  84. package/dist/common/uriParser.js.map +1 -1
  85. package/dist/common/workspaceEditUtils.js +7 -4
  86. package/dist/common/workspaceEditUtils.js.map +1 -1
  87. package/dist/languageServerBase.d.ts +32 -30
  88. package/dist/languageServerBase.js +274 -336
  89. package/dist/languageServerBase.js.map +1 -1
  90. package/dist/languageService/analyzerServiceExecutor.js +0 -1
  91. package/dist/languageService/analyzerServiceExecutor.js.map +1 -1
  92. package/dist/languageService/callHierarchyProvider.d.ts +16 -12
  93. package/dist/languageService/callHierarchyProvider.js +125 -41
  94. package/dist/languageService/callHierarchyProvider.js.map +1 -1
  95. package/dist/languageService/definitionProvider.d.ts +23 -9
  96. package/dist/languageService/definitionProvider.js +116 -91
  97. package/dist/languageService/definitionProvider.js.map +1 -1
  98. package/dist/languageService/documentHighlightProvider.d.ts +8 -3
  99. package/dist/languageService/documentHighlightProvider.js +17 -6
  100. package/dist/languageService/documentHighlightProvider.js.map +1 -1
  101. package/dist/languageService/documentSymbolCollector.d.ts +2 -2
  102. package/dist/languageService/documentSymbolCollector.js +4 -3
  103. package/dist/languageService/documentSymbolCollector.js.map +1 -1
  104. package/dist/languageService/documentSymbolProvider.js +5 -3
  105. package/dist/languageService/documentSymbolProvider.js.map +1 -1
  106. package/dist/languageService/hoverProvider.js +1 -1
  107. package/dist/languageService/hoverProvider.js.map +1 -1
  108. package/dist/languageService/insertionPointUtils.js +3 -3
  109. package/dist/languageService/insertionPointUtils.js.map +1 -1
  110. package/dist/languageService/navigationUtils.d.ts +6 -0
  111. package/dist/languageService/navigationUtils.js +28 -0
  112. package/dist/languageService/navigationUtils.js.map +1 -0
  113. package/dist/languageService/quickActions.d.ts +2 -2
  114. package/dist/languageService/quickActions.js +12 -1
  115. package/dist/languageService/quickActions.js.map +1 -1
  116. package/dist/languageService/referencesProvider.d.ts +8 -2
  117. package/dist/languageService/referencesProvider.js +81 -3
  118. package/dist/languageService/referencesProvider.js.map +1 -1
  119. package/dist/languageService/renameModuleProvider.d.ts +13 -13
  120. package/dist/languageService/renameModuleProvider.js +43 -43
  121. package/dist/languageService/renameModuleProvider.js.map +1 -1
  122. package/dist/languageService/signatureHelpProvider.d.ts +19 -23
  123. package/dist/languageService/signatureHelpProvider.js +111 -18
  124. package/dist/languageService/signatureHelpProvider.js.map +1 -1
  125. package/dist/parser/characterStream.d.ts +3 -3
  126. package/dist/parser/characterStream.js +12 -12
  127. package/dist/parser/characterStream.js.map +1 -1
  128. package/dist/parser/parser.d.ts +1 -1
  129. package/dist/parser/parser.js.map +1 -1
  130. package/dist/pyright.js +57 -54
  131. package/dist/pyright.js.map +1 -1
  132. package/dist/pyrightFileSystem.d.ts +1 -1
  133. package/dist/pyrightFileSystem.js +21 -21
  134. package/dist/pyrightFileSystem.js.map +1 -1
  135. package/dist/readonlyAugmentedFileSystem.d.ts +6 -6
  136. package/dist/readonlyAugmentedFileSystem.js +28 -28
  137. package/dist/readonlyAugmentedFileSystem.js.map +1 -1
  138. package/dist/server.js +6 -6
  139. package/dist/server.js.map +1 -1
  140. package/dist/tests/chainedSourceFiles.test.js +1 -1
  141. package/dist/tests/chainedSourceFiles.test.js.map +1 -1
  142. package/dist/tests/checker.test.js +1 -1
  143. package/dist/tests/harness/fourslash/testLanguageService.d.ts +3 -3
  144. package/dist/tests/harness/fourslash/testLanguageService.js.map +1 -1
  145. package/dist/tests/harness/fourslash/testState.d.ts +8 -8
  146. package/dist/tests/harness/fourslash/testState.js +109 -99
  147. package/dist/tests/harness/fourslash/testState.js.map +1 -1
  148. package/dist/tests/harness/vfs/filesystem.d.ts +8 -8
  149. package/dist/tests/harness/vfs/filesystem.js +68 -68
  150. package/dist/tests/harness/vfs/filesystem.js.map +1 -1
  151. package/dist/tests/importStatementUtils.test.js +34 -0
  152. package/dist/tests/importStatementUtils.test.js.map +1 -1
  153. package/dist/tests/moveSymbol.updateReference.test.js +14 -0
  154. package/dist/tests/moveSymbol.updateReference.test.js.map +1 -1
  155. package/dist/tests/signatureHelp.test.js +5 -1
  156. package/dist/tests/signatureHelp.test.js.map +1 -1
  157. package/dist/tests/sourceFile.test.js +1 -1
  158. package/dist/tests/sourceFile.test.js.map +1 -1
  159. package/dist/tests/testStateUtils.js +1 -1
  160. package/dist/tests/testStateUtils.js.map +1 -1
  161. package/dist/tests/typeEvaluator1.test.js +8 -0
  162. package/dist/tests/typeEvaluator1.test.js.map +1 -1
  163. package/dist/tests/typeEvaluator2.test.js +12 -0
  164. package/dist/tests/typeEvaluator2.test.js.map +1 -1
  165. package/dist/tests/typeEvaluator3.test.js +1 -1
  166. package/package.json +1 -1
@@ -14,6 +14,7 @@ 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");
17
+ const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
17
18
  const backgroundAnalysisProgram_1 = require("./analyzer/backgroundAnalysisProgram");
18
19
  const cacheManager_1 = require("./analyzer/cacheManager");
19
20
  const service_1 = require("./analyzer/service");
@@ -33,9 +34,14 @@ const stringUtils_1 = require("./common/stringUtils");
33
34
  const uriParser_1 = require("./common/uriParser");
34
35
  const workspaceEditUtils_1 = require("./common/workspaceEditUtils");
35
36
  const analyzerServiceExecutor_1 = require("./languageService/analyzerServiceExecutor");
37
+ const callHierarchyProvider_1 = require("./languageService/callHierarchyProvider");
36
38
  const definitionProvider_1 = require("./languageService/definitionProvider");
39
+ const documentHighlightProvider_1 = require("./languageService/documentHighlightProvider");
37
40
  const documentSymbolProvider_1 = require("./languageService/documentSymbolProvider");
38
41
  const hoverProvider_1 = require("./languageService/hoverProvider");
42
+ const navigationUtils_1 = require("./languageService/navigationUtils");
43
+ const referencesProvider_1 = require("./languageService/referencesProvider");
44
+ const signatureHelpProvider_1 = require("./languageService/signatureHelpProvider");
39
45
  const localize_1 = require("./localization/localize");
40
46
  const pyrightFileSystem_1 = require("./pyrightFileSystem");
41
47
  const workspaceFactory_1 = require("./workspaceFactory");
@@ -99,10 +105,10 @@ var VSDiagnosticRank;
99
105
  VSDiagnosticRank.Lowest = 500;
100
106
  })(VSDiagnosticRank || (VSDiagnosticRank = {}));
101
107
  class LanguageServerBase {
102
- constructor(_serverOptions, _connection, console, uriParserFactory = (fs) => new uriParser_1.UriParser(fs)) {
108
+ constructor(serverOptions, connection, console, uriParserFactory = (fs) => new uriParser_1.UriParser(fs)) {
103
109
  var _a, _b;
104
- this._serverOptions = _serverOptions;
105
- this._connection = _connection;
110
+ this.serverOptions = serverOptions;
111
+ this.connection = connection;
106
112
  this.console = console;
107
113
  this._lastTriggerKind = vscode_languageserver_1.CompletionTriggerKind.Invoked;
108
114
  this._initialized = false;
@@ -131,33 +137,124 @@ class LanguageServerBase {
131
137
  supportsTaskItemDiagnosticTag: false,
132
138
  completionItemResolveSupportsAdditionalTextEdits: false,
133
139
  };
140
+ this.openFileMap = new Map();
134
141
  // Stash the base directory into a global variable.
135
142
  // This must happen before fs.getModulePath().
136
- global.__rootDirectory = _serverOptions.rootDirectory;
137
- this.console.info(`${_serverOptions.productName} language server ${_serverOptions.version && _serverOptions.version + ' '}starting`);
138
- this.console.info(`Server root directory: ${_serverOptions.rootDirectory}`);
139
- this._cacheManager = new cacheManager_1.CacheManager();
140
- this._serviceFS = new pyrightFileSystem_1.PyrightFileSystem(this._serverOptions.fileSystem);
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));
143
+ global.__rootDirectory = serverOptions.rootDirectory;
144
+ this.console.info(`${serverOptions.productName} language server ${serverOptions.version && serverOptions.version + ' '}starting`);
145
+ this.console.info(`Server root directory: ${serverOptions.rootDirectory}`);
146
+ this.cacheManager = new cacheManager_1.CacheManager();
147
+ this.fs = new pyrightFileSystem_1.PyrightFileSystem(this.serverOptions.fileSystem);
148
+ this.uriParser = uriParserFactory(this.fs);
149
+ this.workspaceFactory = new workspaceFactory_1.WorkspaceFactory(this.console, this.uriParser, this.createAnalyzerServiceForWorkspace.bind(this), this.isPythonPathImmutable.bind(this), this.onWorkspaceCreated.bind(this));
143
150
  // Set the working directory to a known location within
144
151
  // the extension directory. Otherwise the execution of
145
152
  // python can have unintended and surprising results.
146
- const moduleDirectory = this._serviceFS.getModulePath();
153
+ const moduleDirectory = this.fs.getModulePath();
147
154
  if (moduleDirectory) {
148
- this._serviceFS.chdir(moduleDirectory);
155
+ this.fs.chdir(moduleDirectory);
149
156
  }
150
157
  // Set up callbacks.
151
- this.setupConnection((_a = _serverOptions.supportedCommands) !== null && _a !== void 0 ? _a : [], (_b = _serverOptions.supportedCodeActions) !== null && _b !== void 0 ? _b : []);
158
+ this.setupConnection((_a = serverOptions.supportedCommands) !== null && _a !== void 0 ? _a : [], (_b = serverOptions.supportedCodeActions) !== null && _b !== void 0 ? _b : []);
152
159
  this._progressReporter = new progressReporter_1.ProgressReportTracker(this.createProgressReporter());
153
160
  // Listen on the connection.
154
- this._connection.listen();
161
+ this.connection.listen();
155
162
  // Setup extensions
156
163
  extensibility_1.Extensions.createLanguageServiceExtensions(this);
157
164
  }
165
+ // Provides access to the client's window.
166
+ get window() {
167
+ return this.connection.window;
168
+ }
169
+ get supportAdvancedEdits() {
170
+ return this.client.hasDocumentChangeCapability && this.client.hasDocumentAnnotationCapability;
171
+ }
158
172
  // Convert uri to path
159
173
  decodeTextDocumentUri(uriString) {
160
- return this._uriParser.decodeTextDocumentUri(uriString);
174
+ return this.uriParser.decodeTextDocumentUri(uriString);
175
+ }
176
+ // Creates a service instance that's used for analyzing a
177
+ // program within a workspace.
178
+ createAnalyzerService(name, services, libraryReanalysisTimeProvider) {
179
+ var _a;
180
+ this.console.info(`Starting service instance "${name}"`);
181
+ const serviceId = (0, service_1.getNextServiceId)(name);
182
+ const service = new service_1.AnalyzerService(name, (_a = services === null || services === void 0 ? void 0 : services.fs) !== null && _a !== void 0 ? _a : this.fs, {
183
+ console: this.console,
184
+ hostFactory: this.createHost.bind(this),
185
+ importResolverFactory: this.createImportResolver.bind(this),
186
+ backgroundAnalysis: services ? services.backgroundAnalysis : this.createBackgroundAnalysis(serviceId),
187
+ maxAnalysisTime: this.serverOptions.maxAnalysisTimeInForeground,
188
+ backgroundAnalysisProgramFactory: this.createBackgroundAnalysisProgram.bind(this),
189
+ cancellationProvider: this.serverOptions.cancellationProvider,
190
+ libraryReanalysisTimeProvider,
191
+ cacheManager: this.cacheManager,
192
+ serviceId,
193
+ });
194
+ service.setCompletionCallback((results) => this.onAnalysisCompletedHandler(service.fs, results));
195
+ return service;
196
+ }
197
+ async test_getWorkspaces() {
198
+ const workspaces = [...this.workspaceFactory.items()];
199
+ for (const workspace of workspaces) {
200
+ await workspace.isInitialized.promise;
201
+ }
202
+ return workspaces;
203
+ }
204
+ async getWorkspaceForFile(filePath, pythonPath) {
205
+ return this.workspaceFactory.getWorkspaceForFile(filePath, pythonPath);
206
+ }
207
+ async getContainingWorkspacesForFile(filePath) {
208
+ return this.workspaceFactory.getContainingWorkspacesForFile(filePath);
209
+ }
210
+ reanalyze() {
211
+ this.workspaceFactory.items().forEach((workspace) => {
212
+ workspace.service.invalidateAndForceReanalysis();
213
+ });
214
+ }
215
+ restart() {
216
+ this.workspaceFactory.items().forEach((workspace) => {
217
+ workspace.service.restart();
218
+ });
219
+ }
220
+ updateSettingsForAllWorkspaces() {
221
+ const tasks = [];
222
+ this.workspaceFactory.items().forEach((workspace) => {
223
+ // Updating settings can change workspace's file ownership. Make workspace uninitialized so that
224
+ // features can wait until workspace gets new settings.
225
+ // the file's ownership can also changed by `pyrightconfig.json` changes, but those are synchronous
226
+ // operation, so it won't affect this.
227
+ workspace.isInitialized = workspace.isInitialized.reset();
228
+ tasks.push(this.updateSettingsForWorkspace(workspace, workspace.isInitialized));
229
+ });
230
+ Promise.all(tasks).then(() => {
231
+ this._setupFileWatcher();
232
+ });
233
+ }
234
+ async updateSettingsForWorkspace(workspace, status, serverSettings) {
235
+ var _a;
236
+ status === null || status === void 0 ? void 0 : status.markCalled();
237
+ serverSettings = serverSettings !== null && serverSettings !== void 0 ? serverSettings : (await this.getSettings(workspace));
238
+ // Set logging level first.
239
+ this.console.level = (_a = serverSettings.logLevel) !== null && _a !== void 0 ? _a : console_1.LogLevel.Info;
240
+ // Apply the new path to the workspace (before restarting the service).
241
+ serverSettings.pythonPath = this.workspaceFactory.applyPythonPath(workspace, serverSettings.pythonPath);
242
+ // Then use the updated settings to restart the service.
243
+ this.updateOptionsAndRestartService(workspace, serverSettings);
244
+ workspace.disableLanguageServices = !!serverSettings.disableLanguageServices;
245
+ workspace.disableOrganizeImports = !!serverSettings.disableOrganizeImports;
246
+ // Don't use workspace.isInitialized directly since it might have been
247
+ // reset due to pending config change event.
248
+ // The workspace is now open for business.
249
+ status === null || status === void 0 ? void 0 : status.resolve();
250
+ }
251
+ updateOptionsAndRestartService(workspace, serverSettings, typeStubTargetImportName) {
252
+ var _a;
253
+ analyzerServiceExecutor_1.AnalyzerServiceExecutor.runWithOptions(this.rootPath, workspace, serverSettings, typeStubTargetImportName);
254
+ workspace.searchPathsToWatch = (_a = workspace.service.librarySearchPathsToWatch) !== null && _a !== void 0 ? _a : [];
255
+ }
256
+ get allowModuleRename() {
257
+ return false;
161
258
  }
162
259
  isPythonPathImmutable(filePath) {
163
260
  // This function is called to determine if the file is using
@@ -174,19 +271,16 @@ class LanguageServerBase {
174
271
  if (section !== undefined) {
175
272
  item.section = section;
176
273
  }
177
- return this._connection.workspace.getConfiguration(item);
274
+ return this.connection.workspace.getConfiguration(item);
178
275
  }
179
- if (this._defaultClientConfig) {
180
- return (0, collectionUtils_1.getNestedProperty)(this._defaultClientConfig, section);
276
+ if (this.defaultClientConfig) {
277
+ return (0, collectionUtils_1.getNestedProperty)(this.defaultClientConfig, section);
181
278
  }
182
279
  return undefined;
183
280
  }
184
281
  isOpenFilesOnly(diagnosticMode) {
185
282
  return diagnosticMode !== 'workspace';
186
283
  }
187
- get allowModuleRename() {
188
- return false;
189
- }
190
284
  getSeverityOverrides(value) {
191
285
  const enumValue = value;
192
286
  if ((0, commandLineOptions_1.getDiagnosticSeverityOverrides)().includes(enumValue)) {
@@ -205,87 +299,36 @@ class LanguageServerBase {
205
299
  return new backgroundAnalysisProgram_1.BackgroundAnalysisProgram(console, configOptions, importResolver, backgroundAnalysis, maxAnalysisTime,
206
300
  /* disableChecker */ undefined, cacheManager);
207
301
  }
208
- // Provides access to the client's window.
209
- get window() {
210
- return this._connection.window;
211
- }
212
- get supportAdvancedEdits() {
213
- return this.client.hasDocumentChangeCapability && this.client.hasDocumentAnnotationCapability;
214
- }
215
- // Creates a service instance that's used for analyzing a
216
- // program within a workspace.
217
- createAnalyzerService(name, services, libraryReanalysisTimeProvider) {
218
- var _a;
219
- this.console.info(`Starting service instance "${name}"`);
220
- const serviceId = (0, service_1.getNextServiceId)(name);
221
- const service = new service_1.AnalyzerService(name, (_a = services === null || services === void 0 ? void 0 : services.fs) !== null && _a !== void 0 ? _a : this._serviceFS, {
222
- console: this.console,
223
- hostFactory: this.createHost.bind(this),
224
- importResolverFactory: this.createImportResolver.bind(this),
225
- backgroundAnalysis: services ? services.backgroundAnalysis : this.createBackgroundAnalysis(serviceId),
226
- maxAnalysisTime: this._serverOptions.maxAnalysisTimeInForeground,
227
- backgroundAnalysisProgramFactory: this.createBackgroundAnalysisProgram.bind(this),
228
- cancellationProvider: this._serverOptions.cancellationProvider,
229
- libraryReanalysisTimeProvider,
230
- cacheManager: this._cacheManager,
231
- serviceId,
232
- });
233
- service.setCompletionCallback((results) => this.onAnalysisCompletedHandler(service.fs, results));
234
- return service;
235
- }
236
- async test_getWorkspaces() {
237
- const workspaces = [...this._workspaceFactory.items()];
238
- for (const workspace of workspaces) {
239
- await workspace.isInitialized.promise;
240
- }
241
- return workspaces;
242
- }
243
- async getWorkspaceForFile(filePath, pythonPath) {
244
- return this._workspaceFactory.getWorkspaceForFile(filePath, pythonPath);
245
- }
246
- async getContainingWorkspacesForFile(filePath) {
247
- return this._workspaceFactory.getContainingWorkspacesForFile(filePath);
248
- }
249
- reanalyze() {
250
- this._workspaceFactory.items().forEach((workspace) => {
251
- workspace.service.invalidateAndForceReanalysis();
252
- });
253
- }
254
- restart() {
255
- this._workspaceFactory.items().forEach((workspace) => {
256
- workspace.service.restart();
257
- });
258
- }
259
302
  setupConnection(supportedCommands, supportedCodeActions) {
260
303
  // After the server has started the client sends an initialize request. The server receives
261
304
  // in the passed params the rootPath of the workspace plus the client capabilities.
262
- this._connection.onInitialize((params) => this.initialize(params, supportedCommands, supportedCodeActions));
263
- this._connection.onInitialized(() => this.onInitialized());
264
- this._connection.onDidChangeConfiguration((params) => this.onDidChangeConfiguration(params));
265
- this._connection.onCodeAction((params, token) => this.executeCodeAction(params, token));
266
- this._connection.onDefinition(async (params, token) => this.onDefinition(params, token));
267
- this._connection.onDeclaration(async (params, token) => this.onDeclaration(params, token));
268
- this._connection.onTypeDefinition(async (params, token) => this.onTypeDefinition(params, token));
269
- this._connection.onReferences(async (params, token, workDoneReporter, resultReporter) => this.onReferences(params, token, workDoneReporter, resultReporter));
270
- this._connection.onDocumentSymbol(async (params, token) => this.onDocumentSymbol(params, token));
271
- this._connection.onWorkspaceSymbol(async (params, token, _, resultReporter) => this.onWorkspaceSymbol(params, token, resultReporter));
272
- this._connection.onHover(async (params, token) => this.onHover(params, token));
273
- this._connection.onDocumentHighlight(async (params, token) => this.onDocumentHighlight(params, token));
274
- this._connection.onSignatureHelp(async (params, token) => this.onSignatureHelp(params, token));
275
- this._connection.onCompletion((params, token) => this.onCompletion(params, token));
276
- this._connection.onCompletionResolve(async (params, token) => this.onCompletionResolve(params, token));
277
- this._connection.onPrepareRename(async (params, token) => this.onPrepareRenameRequest(params, token));
278
- this._connection.onRenameRequest(async (params, token) => this.onRenameRequest(params, token));
279
- const callHierarchy = this._connection.languages.callHierarchy;
305
+ this.connection.onInitialize((params) => this.initialize(params, supportedCommands, supportedCodeActions));
306
+ this.connection.onInitialized(() => this.onInitialized());
307
+ this.connection.onDidChangeConfiguration((params) => this.onDidChangeConfiguration(params));
308
+ this.connection.onCodeAction((params, token) => this.executeCodeAction(params, token));
309
+ this.connection.onDefinition(async (params, token) => this.onDefinition(params, token));
310
+ this.connection.onDeclaration(async (params, token) => this.onDeclaration(params, token));
311
+ this.connection.onTypeDefinition(async (params, token) => this.onTypeDefinition(params, token));
312
+ this.connection.onReferences(async (params, token, workDoneReporter, resultReporter) => this.onReferences(params, token, workDoneReporter, resultReporter));
313
+ this.connection.onDocumentSymbol(async (params, token) => this.onDocumentSymbol(params, token));
314
+ this.connection.onWorkspaceSymbol(async (params, token, _, resultReporter) => this.onWorkspaceSymbol(params, token, resultReporter));
315
+ this.connection.onHover(async (params, token) => this.onHover(params, token));
316
+ this.connection.onDocumentHighlight(async (params, token) => this.onDocumentHighlight(params, token));
317
+ this.connection.onSignatureHelp(async (params, token) => this.onSignatureHelp(params, token));
318
+ this.connection.onCompletion((params, token) => this.onCompletion(params, token));
319
+ this.connection.onCompletionResolve(async (params, token) => this.onCompletionResolve(params, token));
320
+ this.connection.onPrepareRename(async (params, token) => this.onPrepareRenameRequest(params, token));
321
+ this.connection.onRenameRequest(async (params, token) => this.onRenameRequest(params, token));
322
+ const callHierarchy = this.connection.languages.callHierarchy;
280
323
  callHierarchy.onPrepare(async (params, token) => this.onPrepare(params, token));
281
324
  callHierarchy.onIncomingCalls(async (params, token) => this.onIncomingCalls(params, token));
282
325
  callHierarchy.onOutgoingCalls(async (params, token) => this.onOutgoingCalls(params, token));
283
- this._connection.onDidOpenTextDocument(async (params) => this.onDidOpenTextDocument(params));
284
- this._connection.onDidChangeTextDocument(async (params) => this.onDidChangeTextDocument(params));
285
- this._connection.onDidCloseTextDocument(async (params) => this.onDidCloseTextDocument(params));
286
- this._connection.onDidChangeWatchedFiles((params) => this.onDidChangeWatchedFiles(params));
287
- this._connection.onExecuteCommand(async (params, token, reporter) => this.onExecuteCommand(params, token, reporter));
288
- this._connection.onShutdown(async (token) => this.onShutdown(token));
326
+ this.connection.onDidOpenTextDocument(async (params) => this.onDidOpenTextDocument(params));
327
+ this.connection.onDidChangeTextDocument(async (params) => this.onDidChangeTextDocument(params));
328
+ this.connection.onDidCloseTextDocument(async (params) => this.onDidCloseTextDocument(params));
329
+ this.connection.onDidChangeWatchedFiles((params) => this.onDidChangeWatchedFiles(params));
330
+ this.connection.onExecuteCommand(async (params, token, reporter) => this.onExecuteCommand(params, token, reporter));
331
+ this.connection.onShutdown(async (token) => this.onShutdown(token));
289
332
  }
290
333
  initialize(params, supportedCommands, supportedCodeActions) {
291
334
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19;
@@ -327,7 +370,7 @@ class LanguageServerBase {
327
370
  this.client.completionItemResolveSupportsAdditionalTextEdits =
328
371
  !!((_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'));
329
372
  // Create a service instance for each of the workspace folders.
330
- this._workspaceFactory.handleInitialize(params);
373
+ this.workspaceFactory.handleInitialize(params);
331
374
  const result = {
332
375
  capabilities: {
333
376
  textDocumentSync: vscode_languageserver_1.TextDocumentSyncKind.Incremental,
@@ -382,64 +425,37 @@ class LanguageServerBase {
382
425
  this.updateSettingsForAllWorkspaces();
383
426
  return;
384
427
  }
385
- this._connection.workspace.onDidChangeWorkspaceFolders((event) => {
386
- this._workspaceFactory.handleWorkspaceFoldersChanged(event);
428
+ this.connection.workspace.onDidChangeWorkspaceFolders((event) => {
429
+ this.workspaceFactory.handleWorkspaceFoldersChanged(event);
387
430
  this._setupFileWatcher();
388
431
  });
389
432
  this._setupFileWatcher();
390
433
  }
391
- _setupFileWatcher() {
392
- if (!this.client.hasWatchFileCapability) {
393
- return;
394
- }
395
- const watchKind = vscode_languageserver_1.WatchKind.Create | vscode_languageserver_1.WatchKind.Change | vscode_languageserver_1.WatchKind.Delete;
396
- // Set default (config files and all workspace files) first.
397
- const watchers = [
398
- ...service_1.configFileNames.map((fileName) => ({ globPattern: `**/${fileName}`, kind: watchKind })),
399
- { globPattern: '**', kind: watchKind },
400
- ];
401
- // Add all python search paths to watch list
402
- if (this.client.hasWatchFileRelativePathCapability) {
403
- // Dedup search paths from all workspaces.
404
- // Get rid of any search path under workspace root since it is already watched by
405
- // "**" above.
406
- const foldersToWatch = (0, pathUtils_1.deduplicateFolders)(this._workspaceFactory
407
- .getNonDefaultWorkspaces()
408
- .map((w) => w.searchPathsToWatch.filter((p) => !p.startsWith(w.rootPath))));
409
- foldersToWatch.forEach((p) => {
410
- const globPattern = (0, pathUtils_1.isFile)(this._serviceFS, p, /* treatZipDirectoryAsFile */ true)
411
- ? { baseUri: (0, pathUtils_1.convertPathToUri)(this._serviceFS, (0, pathUtils_1.getDirectoryPath)(p)), pattern: (0, pathUtils_1.getFileName)(p) }
412
- : { baseUri: (0, pathUtils_1.convertPathToUri)(this._serviceFS, p), pattern: '**' };
413
- watchers.push({ globPattern, kind: watchKind });
414
- });
415
- }
416
- // File watcher is pylance wide service. Dispose all existing file watchers and create new ones.
417
- this._connection.client.register(vscode_languageserver_1.DidChangeWatchedFilesNotification.type, { watchers }).then((d) => {
418
- if (this._lastFileWatcherRegistration) {
419
- this._lastFileWatcherRegistration.dispose();
420
- }
421
- this._lastFileWatcherRegistration = d;
422
- });
423
- }
424
434
  onDidChangeConfiguration(params) {
425
435
  this.console.log(`Received updated settings`);
426
436
  if (params === null || params === void 0 ? void 0 : params.settings) {
427
- this._defaultClientConfig = params === null || params === void 0 ? void 0 : params.settings;
437
+ this.defaultClientConfig = params === null || params === void 0 ? void 0 : params.settings;
428
438
  }
429
439
  this.updateSettingsForAllWorkspaces();
430
440
  }
431
441
  async onDefinition(params, 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));
442
+ return this.getDefinitions(params, token, this.client.hasGoToDeclarationCapability ? definitionProvider_1.DefinitionFilter.PreferSource : definitionProvider_1.DefinitionFilter.All, (workspace, filePath, position, filter, token) => workspace.service.run((program) => {
443
+ return new definitionProvider_1.DefinitionProvider(program, filePath, position, filter, token).getDefinitions();
444
+ }, token));
433
445
  }
434
446
  async onDeclaration(params, 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));
447
+ return this.getDefinitions(params, token, this.client.hasGoToDeclarationCapability ? definitionProvider_1.DefinitionFilter.PreferStubs : definitionProvider_1.DefinitionFilter.All, (workspace, filePath, position, filter, token) => workspace.service.run((program) => {
448
+ return new definitionProvider_1.DefinitionProvider(program, filePath, position, filter, token).getDefinitions();
449
+ }, token));
436
450
  }
437
451
  async onTypeDefinition(params, token) {
438
- return this.getDefinitions(params, token, definitionProvider_1.DefinitionFilter.All, (workspace, filePath, position, _, token) => workspace.service.getTypeDefinitionForPosition(filePath, position, token));
452
+ return this.getDefinitions(params, token, definitionProvider_1.DefinitionFilter.All, (workspace, filePath, position, _, token) => workspace.service.run((program) => {
453
+ return new definitionProvider_1.TypeDefinitionProvider(program, filePath, position, token).getDefinitions();
454
+ }, token));
439
455
  }
440
456
  async getDefinitions(params, token, filter, getDefinitionsFunc) {
441
457
  this.recordUserInteractionTime();
442
- const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
458
+ const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
443
459
  const workspace = await this.getWorkspaceForFile(filePath);
444
460
  if (workspace.disableLanguageServices) {
445
461
  return undefined;
@@ -464,22 +480,14 @@ class LanguageServerBase {
464
480
  const source = progress.source;
465
481
  this._pendingFindAllRefsCancellationSource = source;
466
482
  try {
467
- const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
483
+ const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
468
484
  const workspace = await this.getWorkspaceForFile(filePath);
469
485
  if (workspace.disableLanguageServices) {
470
486
  return;
471
487
  }
472
- const convert = (locs) => {
473
- return locs
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));
476
- };
477
- const locations = [];
478
- const reporter = resultReporter
479
- ? (locs) => resultReporter.report(convert(locs))
480
- : (locs) => (0, collectionUtils_1.appendArray)(locations, convert(locs));
481
- workspace.service.reportReferencesForPosition(filePath, position, params.context.includeDeclaration, reporter, source.token);
482
- return locations;
488
+ return workspace.service.run((program) => {
489
+ return new referencesProvider_1.ReferencesProvider(program, source.token).reportReferences(filePath, position, params.context.includeDeclaration, resultReporter);
490
+ }, token);
483
491
  }
484
492
  finally {
485
493
  progress.reporter.done();
@@ -488,7 +496,7 @@ class LanguageServerBase {
488
496
  }
489
497
  async onDocumentSymbol(params, token) {
490
498
  this.recordUserInteractionTime();
491
- const filePath = this._uriParser.decodeTextDocumentUri(params.textDocument.uri);
499
+ const filePath = this.uriParser.decodeTextDocumentUri(params.textDocument.uri);
492
500
  const workspace = await this.getWorkspaceForFile(filePath);
493
501
  if (workspace.disableLanguageServices) {
494
502
  return undefined;
@@ -505,7 +513,7 @@ class LanguageServerBase {
505
513
  const reporter = resultReporter
506
514
  ? (symbols) => resultReporter.report(symbols)
507
515
  : (symbols) => (0, collectionUtils_1.appendArray)(symbolList, symbols);
508
- for (const workspace of this._workspaceFactory.items()) {
516
+ for (const workspace of this.workspaceFactory.items()) {
509
517
  await workspace.isInitialized.promise;
510
518
  if (!workspace.disableLanguageServices && !workspace.disableWorkspaceSymbol) {
511
519
  workspace.service.reportSymbolsForWorkspace(params.query, reporter, token);
@@ -514,96 +522,28 @@ class LanguageServerBase {
514
522
  return symbolList;
515
523
  }
516
524
  async onHover(params, token) {
517
- const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
525
+ const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
518
526
  const workspace = await this.getWorkspaceForFile(filePath);
519
527
  return workspace.service.run((program) => {
520
- return new hoverProvider_1.HoverProvider(program, filePath, position, this.client.hoverContentFormat, !!this._serverOptions.supportsTelemetry, token).getHover();
528
+ return new hoverProvider_1.HoverProvider(program, filePath, position, this.client.hoverContentFormat, !!this.serverOptions.supportsTelemetry, token).getHover();
521
529
  }, token);
522
530
  }
523
531
  async onDocumentHighlight(params, token) {
524
- const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
532
+ const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
525
533
  const workspace = await this.getWorkspaceForFile(filePath);
526
- return workspace.service.getDocumentHighlight(filePath, position, token);
534
+ return workspace.service.run((program) => {
535
+ return new documentHighlightProvider_1.DocumentHighlightProvider(program, filePath, position, token).getDocumentHighlight();
536
+ }, token);
527
537
  }
528
538
  async onSignatureHelp(params, token) {
529
- var _a, _b;
530
- const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
539
+ const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
531
540
  const workspace = await this.getWorkspaceForFile(filePath);
532
541
  if (workspace.disableLanguageServices) {
533
542
  return;
534
543
  }
535
- const signatureHelpResults = workspace.service.getSignatureHelpForPosition(filePath, position, this.client.signatureDocFormat, token);
536
- if (!signatureHelpResults) {
537
- return undefined;
538
- }
539
- const signatures = signatureHelpResults.signatures.map((sig) => {
540
- let paramInfo = [];
541
- if (sig.parameters) {
542
- paramInfo = sig.parameters.map((param) => vscode_languageserver_1.ParameterInformation.create(this.client.hasSignatureLabelOffsetCapability
543
- ? [param.startOffset, param.endOffset]
544
- : param.text, param.documentation));
545
- }
546
- const sigInfo = vscode_languageserver_1.SignatureInformation.create(sig.label, /* documentation */ undefined, ...paramInfo);
547
- if (sig.documentation !== undefined) {
548
- sigInfo.documentation = sig.documentation;
549
- }
550
- if (sig.activeParameter !== undefined) {
551
- sigInfo.activeParameter = sig.activeParameter;
552
- }
553
- return sigInfo;
554
- });
555
- // A signature is active if it contains an active parameter,
556
- // or if both the signature and its invocation have no parameters.
557
- const isActive = (sig) => { var _a; return sig.activeParameter !== undefined || (!signatureHelpResults.callHasParameters && !((_a = sig.parameters) === null || _a === void 0 ? void 0 : _a.length)); };
558
- let activeSignature = signatures.findIndex(isActive);
559
- if (activeSignature === -1) {
560
- activeSignature = undefined;
561
- }
562
- let activeParameter = activeSignature !== undefined ? signatures[activeSignature].activeParameter : undefined;
563
- // Check if we should reuse the user's signature selection. If the retrigger was not "invoked"
564
- // (i.e., the signature help call was automatically generated by the client due to some navigation
565
- // or text change), check to see if the previous signature is still "active". If so, we mark it as
566
- // active in our response.
567
- //
568
- // This isn't a perfect method. For nested calls, we can't tell when we are moving between them.
569
- // Ideally, we would include a token in the signature help responses to compare later, allowing us
570
- // to know when the user's navigated to a nested call (and therefore the old signature's info does
571
- // not apply), but for now manually retriggering the signature help will work around the issue.
572
- if (((_a = params.context) === null || _a === void 0 ? void 0 : _a.isRetrigger) && params.context.triggerKind !== vscode_languageserver_1.SignatureHelpTriggerKind.Invoked) {
573
- const prevActiveSignature = (_b = params.context.activeSignatureHelp) === null || _b === void 0 ? void 0 : _b.activeSignature;
574
- if (prevActiveSignature !== undefined && prevActiveSignature < signatures.length) {
575
- const sig = signatures[prevActiveSignature];
576
- if (isActive(sig)) {
577
- activeSignature = prevActiveSignature;
578
- activeParameter = sig.activeParameter;
579
- }
580
- }
581
- }
582
- if (this.client.hasActiveParameterCapability || activeSignature === undefined) {
583
- // If there is no active parameter, then we want the client to not highlight anything.
584
- // Unfortunately, the LSP spec says that "undefined" or "out of bounds" values should be
585
- // treated as 0, which is the first parameter. That's not what we want, but thankfully
586
- // VS Code (and potentially other clients) choose to handle out of bounds values by
587
- // not highlighting them, which is what we want.
588
- //
589
- // The spec defines activeParameter as uinteger, so use the maximum length of any
590
- // signature's parameter list to ensure that the value is always out of range.
591
- //
592
- // We always set this even if some signature has an active parameter, as this
593
- // value is used as the fallback for signatures that don't explicitly specify an
594
- // active parameter (and we use "undefined" to mean "no active parameter").
595
- //
596
- // We could apply this hack to each individual signature such that they all specify
597
- // activeParameter, but that would make it more difficult to determine which actually
598
- // are active when comparing, and we already have to set this for clients which don't
599
- // support per-signature activeParameter.
600
- //
601
- // See:
602
- // - https://github.com/microsoft/language-server-protocol/issues/1271
603
- // - https://github.com/microsoft/pyright/pull/1783
604
- activeParameter = Math.max(...signatures.map((s) => { var _a, _b; return (_b = (_a = s.parameters) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0; }));
605
- }
606
- return { signatures, activeSignature, activeParameter };
544
+ return workspace.service.run((program) => {
545
+ return new signatureHelpProvider_1.SignatureHelpProvider(program, filePath, position, this.client.signatureDocFormat, this.client.hasSignatureLabelOffsetCapability, this.client.hasActiveParameterCapability, params.context, token).getSignatureHelp();
546
+ }, token);
607
547
  }
608
548
  async onCompletion(params, token) {
609
549
  var _a, _b;
@@ -618,7 +558,7 @@ class LanguageServerBase {
618
558
  const completionIncomplete = this._lastTriggerKind !== vscode_languageserver_1.CompletionTriggerKind.TriggerForIncompleteCompletions ||
619
559
  ((_a = params.context) === null || _a === void 0 ? void 0 : _a.triggerKind) !== vscode_languageserver_1.CompletionTriggerKind.TriggerForIncompleteCompletions;
620
560
  this._lastTriggerKind = (_b = params.context) === null || _b === void 0 ? void 0 : _b.triggerKind;
621
- const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
561
+ const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
622
562
  const workspace = await this.getWorkspaceForFile(filePath);
623
563
  if (workspace.disableLanguageServices) {
624
564
  return;
@@ -633,7 +573,7 @@ class LanguageServerBase {
633
573
  completions.completionList &&
634
574
  completions.completionList.items.length > 0 &&
635
575
  completions.memberAccessInfo.lastKnownModule &&
636
- this._serverOptions.supportsTelemetry) {
576
+ this.serverOptions.supportsTelemetry) {
637
577
  // Just stick it on the first item. It only checks the first one
638
578
  completions.completionList.items[0].data = {
639
579
  ...completions.completionList.items[0].data,
@@ -658,7 +598,7 @@ class LanguageServerBase {
658
598
  }
659
599
  async onPrepareRenameRequest(params, token) {
660
600
  var _a;
661
- const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
601
+ const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
662
602
  const workspace = await this.getWorkspaceForFile(filePath);
663
603
  if (workspace.disableLanguageServices) {
664
604
  return null;
@@ -667,7 +607,7 @@ class LanguageServerBase {
667
607
  return (_a = result === null || result === void 0 ? void 0 : result.range) !== null && _a !== void 0 ? _a : null;
668
608
  }
669
609
  async onRenameRequest(params, token) {
670
- const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
610
+ const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
671
611
  const workspace = await this.getWorkspaceForFile(filePath);
672
612
  if (workspace.disableLanguageServices) {
673
613
  return;
@@ -679,62 +619,51 @@ class LanguageServerBase {
679
619
  return (0, workspaceEditUtils_1.convertToWorkspaceEdit)(workspace.service.fs, editActions);
680
620
  }
681
621
  async onPrepare(params, token) {
682
- const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
622
+ const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
683
623
  const workspace = await this.getWorkspaceForFile(filePath);
684
624
  if (workspace.disableLanguageServices) {
685
625
  return null;
686
626
  }
687
- const callItem = workspace.service.getCallForPosition(filePath, position, token) || null;
688
- if (!callItem) {
689
- return null;
690
- }
691
- if (!this.canNavigateToFile(callItem.uri, workspace.service.fs)) {
692
- return null;
693
- }
694
- // Convert the file path in the item to proper URI.
695
- callItem.uri = (0, pathUtils_1.convertPathToUri)(workspace.service.fs, callItem.uri);
696
- return [callItem];
627
+ return workspace.service.run((program) => {
628
+ return new callHierarchyProvider_1.CallHierarchyProvider(program, filePath, position, token).onPrepare();
629
+ }, token);
697
630
  }
698
631
  async onIncomingCalls(params, token) {
699
- const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.item, params.item.range.start);
632
+ const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.item, params.item.range.start);
700
633
  const workspace = await this.getWorkspaceForFile(filePath);
701
634
  if (workspace.disableLanguageServices) {
702
635
  return null;
703
636
  }
704
- let callItems = workspace.service.getIncomingCallsForPosition(filePath, position, token) || null;
705
- if (!callItems || callItems.length === 0) {
706
- return null;
707
- }
708
- callItems = callItems.filter((item) => this.canNavigateToFile(item.from.uri, workspace.service.fs));
709
- // Convert the file paths in the items to proper URIs.
710
- callItems.forEach((item) => {
711
- item.from.uri = (0, pathUtils_1.convertPathToUri)(workspace.service.fs, item.from.uri);
712
- });
713
- return callItems;
637
+ return workspace.service.run((program) => {
638
+ return new callHierarchyProvider_1.CallHierarchyProvider(program, filePath, position, token).getIncomingCalls();
639
+ }, token);
714
640
  }
715
641
  async onOutgoingCalls(params, token) {
716
- const { filePath, position } = this._uriParser.decodeTextDocumentPosition(params.item, params.item.range.start);
642
+ const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.item, params.item.range.start);
717
643
  const workspace = await this.getWorkspaceForFile(filePath);
718
644
  if (workspace.disableLanguageServices) {
719
645
  return null;
720
646
  }
721
- let callItems = workspace.service.getOutgoingCallsForPosition(filePath, position, token) || null;
722
- if (!callItems || callItems.length === 0) {
723
- return null;
724
- }
725
- callItems = callItems.filter((item) => this.canNavigateToFile(item.to.uri, workspace.service.fs));
726
- // Convert the file paths in the items to proper URIs.
727
- callItems.forEach((item) => {
728
- item.to.uri = (0, pathUtils_1.convertPathToUri)(workspace.service.fs, item.to.uri);
729
- });
730
- return callItems;
647
+ return workspace.service.run((program) => {
648
+ return new callHierarchyProvider_1.CallHierarchyProvider(program, filePath, position, token).getOutgoingCalls();
649
+ }, token);
731
650
  }
732
651
  async onDidOpenTextDocument(params, ipythonMode = sourceFile_1.IPythonMode.None) {
733
- const filePath = this._uriParser.decodeTextDocumentUri(params.textDocument.uri);
734
- if (!this._serviceFS.addUriMap(params.textDocument.uri, filePath)) {
652
+ const filePath = this.uriParser.decodeTextDocumentUri(params.textDocument.uri);
653
+ if (!this.fs.addUriMap(params.textDocument.uri, filePath)) {
735
654
  // We do not support opening 1 file with 2 different uri.
736
655
  return;
737
656
  }
657
+ let doc = this.openFileMap.get(filePath);
658
+ if (doc) {
659
+ // We shouldn't get an open text document request for an already-opened doc.
660
+ this.console.error(`Received redundant open text document command for ${filePath}`);
661
+ doc = vscode_languageserver_textdocument_1.TextDocument.update(doc, [{ text: params.textDocument.text }], params.textDocument.version);
662
+ }
663
+ else {
664
+ doc = vscode_languageserver_textdocument_1.TextDocument.create(filePath, 'python', params.textDocument.version, params.textDocument.text);
665
+ }
666
+ this.openFileMap.set(filePath, doc);
738
667
  // Send this open to all the workspaces that might contain this file.
739
668
  const workspaces = await this.getContainingWorkspacesForFile(filePath);
740
669
  workspaces.forEach((w) => {
@@ -743,20 +672,29 @@ class LanguageServerBase {
743
672
  }
744
673
  async onDidChangeTextDocument(params, ipythonMode = sourceFile_1.IPythonMode.None) {
745
674
  this.recordUserInteractionTime();
746
- const filePath = this._uriParser.decodeTextDocumentUri(params.textDocument.uri);
747
- if (!this._serviceFS.hasUriMapEntry(params.textDocument.uri, filePath)) {
675
+ const filePath = this.uriParser.decodeTextDocumentUri(params.textDocument.uri);
676
+ if (!this.fs.hasUriMapEntry(params.textDocument.uri, filePath)) {
748
677
  // We do not support opening 1 file with 2 different uri.
749
678
  return;
750
679
  }
680
+ let doc = this.openFileMap.get(filePath);
681
+ if (!doc) {
682
+ // We shouldn't get a change text request for a closed doc.
683
+ this.console.error(`Received change text document command for closed file ${filePath}`);
684
+ return;
685
+ }
686
+ doc = vscode_languageserver_textdocument_1.TextDocument.update(doc, params.contentChanges, params.textDocument.version);
687
+ this.openFileMap.set(filePath, doc);
688
+ const newContents = doc.getText();
751
689
  // Send this change to all the workspaces that might contain this file.
752
690
  const workspaces = await this.getContainingWorkspacesForFile(filePath);
753
691
  workspaces.forEach((w) => {
754
- w.service.updateOpenFileContents(filePath, params.textDocument.version, params.contentChanges, ipythonMode);
692
+ w.service.updateOpenFileContents(filePath, params.textDocument.version, newContents, ipythonMode);
755
693
  });
756
694
  }
757
695
  async onDidCloseTextDocument(params) {
758
- const filePath = this._uriParser.decodeTextDocumentUri(params.textDocument.uri);
759
- if (!this._serviceFS.removeUriMap(params.textDocument.uri, filePath)) {
696
+ const filePath = this.uriParser.decodeTextDocumentUri(params.textDocument.uri);
697
+ if (!this.fs.removeUriMap(params.textDocument.uri, filePath)) {
760
698
  // We do not support opening 1 file with 2 different uri.
761
699
  return;
762
700
  }
@@ -765,12 +703,13 @@ class LanguageServerBase {
765
703
  workspaces.forEach((w) => {
766
704
  w.service.setFileClosed(filePath);
767
705
  });
706
+ this.openFileMap.delete(filePath);
768
707
  }
769
708
  onDidChangeWatchedFiles(params) {
770
709
  params.changes.forEach((change) => {
771
- const filePath = this._serviceFS.realCasePath(this._uriParser.decodeTextDocumentUri(change.uri));
710
+ const filePath = this.fs.realCasePath(this.uriParser.decodeTextDocumentUri(change.uri));
772
711
  const eventType = change.type === 1 ? 'add' : 'change';
773
- this._serverOptions.fileWatcherHandler.onFileChange(eventType, filePath);
712
+ this.serverOptions.fileWatcherHandler.onFileChange(eventType, filePath);
774
713
  });
775
714
  }
776
715
  async onExecuteCommand(params, token, reporter) {
@@ -784,12 +723,12 @@ class LanguageServerBase {
784
723
  if (vscode_languageserver_1.WorkspaceEdit.is(result)) {
785
724
  // Tell client to apply edits.
786
725
  // Do not await; the client isn't expecting a result.
787
- this._connection.workspace.applyEdit({ label: `Command '${params.command}'`, edit: result });
726
+ this.connection.workspace.applyEdit({ label: `Command '${params.command}'`, edit: result });
788
727
  }
789
728
  if (commandResult_1.CommandResult.is(result)) {
790
729
  // Tell client to apply edits.
791
730
  // Await so that we return after the edit is complete.
792
- await this._connection.workspace.applyEdit({ label: result.label, edit: result.edits });
731
+ await this.connection.workspace.applyEdit({ label: result.label, edit: result.edits });
793
732
  }
794
733
  return result;
795
734
  };
@@ -814,7 +753,9 @@ class LanguageServerBase {
814
753
  }
815
754
  onShutdown(token) {
816
755
  // Shutdown remaining workspaces.
817
- this._workspaceFactory.clear();
756
+ this.workspaceFactory.clear();
757
+ // Stop tracking all open files.
758
+ this.openFileMap.clear();
818
759
  return Promise.resolve();
819
760
  }
820
761
  resolveWorkspaceCompletionItem(workspace, filePath, item, token) {
@@ -824,20 +765,6 @@ class LanguageServerBase {
824
765
  getWorkspaceCompletionsForPosition(workspace, filePath, position, options, token) {
825
766
  return workspace.service.getCompletionsForPosition(filePath, position, workspace.rootPath, options, undefined, token);
826
767
  }
827
- updateSettingsForAllWorkspaces() {
828
- const tasks = [];
829
- this._workspaceFactory.items().forEach((workspace) => {
830
- // Updating settings can change workspace's file ownership. Make workspace uninitialized so that
831
- // features can wait until workspace gets new settings.
832
- // the file's ownership can also changed by `pyrightconfig.json` changes, but those are synchronous
833
- // operation, so it won't affect this.
834
- workspace.isInitialized = workspace.isInitialized.reset();
835
- tasks.push(this.updateSettingsForWorkspace(workspace, workspace.isInitialized));
836
- });
837
- Promise.all(tasks).then(() => {
838
- this._setupFileWatcher();
839
- });
840
- }
841
768
  getCompletionOptions(workspace, params) {
842
769
  var _a;
843
770
  return {
@@ -867,7 +794,7 @@ class LanguageServerBase {
867
794
  return;
868
795
  }
869
796
  this._sendDiagnostics(this.convertDiagnostics(fs, fileDiag));
870
- this._serviceFS.pendingRequest(fileDiag.filePath, fileDiag.diagnostics.length > 0);
797
+ this.fs.pendingRequest(fileDiag.filePath, fileDiag.diagnostics.length > 0);
871
798
  });
872
799
  if (!this._progressReporter.isEnabled(results)) {
873
800
  // Make sure to disable progress bar if it is currently active.
@@ -891,28 +818,6 @@ class LanguageServerBase {
891
818
  this._progressReporter.end();
892
819
  }
893
820
  }
894
- async updateSettingsForWorkspace(workspace, status, serverSettings) {
895
- var _a;
896
- status === null || status === void 0 ? void 0 : status.markCalled();
897
- serverSettings = serverSettings !== null && serverSettings !== void 0 ? serverSettings : (await this.getSettings(workspace));
898
- // Set logging level first.
899
- this.console.level = (_a = serverSettings.logLevel) !== null && _a !== void 0 ? _a : console_1.LogLevel.Info;
900
- // Apply the new path to the workspace (before restarting the service).
901
- serverSettings.pythonPath = this._workspaceFactory.applyPythonPath(workspace, serverSettings.pythonPath);
902
- // Then use the updated settings to restart the service.
903
- this.updateOptionsAndRestartService(workspace, serverSettings);
904
- workspace.disableLanguageServices = !!serverSettings.disableLanguageServices;
905
- workspace.disableOrganizeImports = !!serverSettings.disableOrganizeImports;
906
- // Don't use workspace.isInitialized directly since it might have been
907
- // reset due to pending config change event.
908
- // The workspace is now open for business.
909
- status === null || status === void 0 ? void 0 : status.resolve();
910
- }
911
- updateOptionsAndRestartService(workspace, serverSettings, typeStubTargetImportName) {
912
- var _a;
913
- analyzerServiceExecutor_1.AnalyzerServiceExecutor.runWithOptions(this.rootPath, workspace, serverSettings, typeStubTargetImportName);
914
- workspace.searchPathsToWatch = (_a = workspace.service.librarySearchPathsToWatch) !== null && _a !== void 0 ? _a : [];
915
- }
916
821
  onWorkspaceCreated(workspace) {
917
822
  // Update settings on this workspace (but only if initialize has happened)
918
823
  if (this._initialized) {
@@ -926,15 +831,63 @@ class LanguageServerBase {
926
831
  // 10 seconds back off for multi workspace.
927
832
  const multiWorkspaceBackOffTime = 10 * 1000;
928
833
  const libraryReanalysisTimeProvider = kinds.length === 1 && kinds[0] === workspaceFactory_1.WellKnownWorkspaceKinds.Regular
929
- ? () => this._workspaceFactory.hasMultipleWorkspaces(kinds[0])
834
+ ? () => this.workspaceFactory.hasMultipleWorkspaces(kinds[0])
930
835
  ? multiWorkspaceBackOffTime
931
836
  : defaultBackOffTime
932
837
  : () => defaultBackOffTime;
933
838
  return this.createAnalyzerService(name, services, libraryReanalysisTimeProvider);
934
839
  }
840
+ recordUserInteractionTime() {
841
+ // Tell all of the services that the user is actively
842
+ // interacting with one or more editors, so they should
843
+ // back off from performing any work.
844
+ this.workspaceFactory.items().forEach((workspace) => {
845
+ workspace.service.recordUserInteractionTime();
846
+ });
847
+ }
848
+ getDocumentationUrlForDiagnosticRule(rule) {
849
+ // Configuration.md is configured to have a link for every rule name.
850
+ return `https://github.com/microsoft/pyright/blob/main/docs/configuration.md#${rule}`;
851
+ }
852
+ canNavigateToFile(path, fs) {
853
+ return (0, navigationUtils_1.canNavigateToFile)(fs, path);
854
+ }
855
+ _setupFileWatcher() {
856
+ if (!this.client.hasWatchFileCapability) {
857
+ return;
858
+ }
859
+ const watchKind = vscode_languageserver_1.WatchKind.Create | vscode_languageserver_1.WatchKind.Change | vscode_languageserver_1.WatchKind.Delete;
860
+ // Set default (config files and all workspace files) first.
861
+ const watchers = [
862
+ ...service_1.configFileNames.map((fileName) => ({ globPattern: `**/${fileName}`, kind: watchKind })),
863
+ { globPattern: '**', kind: watchKind },
864
+ ];
865
+ // Add all python search paths to watch list
866
+ if (this.client.hasWatchFileRelativePathCapability) {
867
+ // Dedup search paths from all workspaces.
868
+ // Get rid of any search path under workspace root since it is already watched by
869
+ // "**" above.
870
+ const foldersToWatch = (0, pathUtils_1.deduplicateFolders)(this.workspaceFactory
871
+ .getNonDefaultWorkspaces()
872
+ .map((w) => w.searchPathsToWatch.filter((p) => !p.startsWith(w.rootPath))));
873
+ foldersToWatch.forEach((p) => {
874
+ const globPattern = (0, pathUtils_1.isFile)(this.fs, p, /* treatZipDirectoryAsFile */ true)
875
+ ? { baseUri: (0, pathUtils_1.convertPathToUri)(this.fs, (0, pathUtils_1.getDirectoryPath)(p)), pattern: (0, pathUtils_1.getFileName)(p) }
876
+ : { baseUri: (0, pathUtils_1.convertPathToUri)(this.fs, p), pattern: '**' };
877
+ watchers.push({ globPattern, kind: watchKind });
878
+ });
879
+ }
880
+ // File watcher is pylance wide service. Dispose all existing file watchers and create new ones.
881
+ this.connection.client.register(vscode_languageserver_1.DidChangeWatchedFilesNotification.type, { watchers }).then((d) => {
882
+ if (this._lastFileWatcherRegistration) {
883
+ this._lastFileWatcherRegistration.dispose();
884
+ }
885
+ this._lastFileWatcherRegistration = d;
886
+ });
887
+ }
935
888
  _sendDiagnostics(params) {
936
889
  for (const param of params) {
937
- this._connection.sendDiagnostics(param);
890
+ this.connection.sendDiagnostics(param);
938
891
  }
939
892
  }
940
893
  _getCompatibleMarkupKind(clientSupportedFormats) {
@@ -952,16 +905,16 @@ class LanguageServerBase {
952
905
  // created by the LSP library. If it's the latter, we'll create a server-initiated
953
906
  // progress reporter.
954
907
  if (reporter.constructor !== nullProgressReporter.constructor) {
955
- return { reporter: reporter, source: (0, cancellationUtils_1.CancelAfter)(this._serverOptions.cancellationProvider, token) };
908
+ return { reporter: reporter, source: (0, cancellationUtils_1.CancelAfter)(this.serverOptions.cancellationProvider, token) };
956
909
  }
957
- const serverInitiatedReporter = await this._connection.window.createWorkDoneProgress();
910
+ const serverInitiatedReporter = await this.connection.window.createWorkDoneProgress();
958
911
  serverInitiatedReporter.begin(title,
959
912
  /* percentage */ undefined,
960
913
  /* message */ undefined,
961
914
  /* cancellable */ true);
962
915
  return {
963
916
  reporter: serverInitiatedReporter,
964
- source: (0, cancellationUtils_1.CancelAfter)(this._serverOptions.cancellationProvider, token, serverInitiatedReporter.token),
917
+ source: (0, cancellationUtils_1.CancelAfter)(this.serverOptions.cancellationProvider, token, serverInitiatedReporter.token),
965
918
  };
966
919
  }
967
920
  _convertDiagnostics(fs, diags) {
@@ -969,7 +922,7 @@ class LanguageServerBase {
969
922
  diags.forEach((diag) => {
970
923
  const severity = convertCategoryToSeverity(diag.category);
971
924
  const rule = diag.getRule();
972
- const vsDiag = vscode_languageserver_1.Diagnostic.create(diag.range, diag.message, severity, rule, this._serverOptions.productName);
925
+ const vsDiag = vscode_languageserver_1.Diagnostic.create(diag.range, diag.message, severity, rule, this.serverOptions.productName);
973
926
  if (diag.category === 3 /* UnusedCode */ ||
974
927
  diag.category === 4 /* UnreachableCode */) {
975
928
  vsDiag.tags = [vscode_languageserver_1.DiagnosticTag.Unnecessary];
@@ -1043,21 +996,6 @@ class LanguageServerBase {
1043
996
  }
1044
997
  return convertedDiags;
1045
998
  }
1046
- recordUserInteractionTime() {
1047
- // Tell all of the services that the user is actively
1048
- // interacting with one or more editors, so they should
1049
- // back off from performing any work.
1050
- this._workspaceFactory.items().forEach((workspace) => {
1051
- workspace.service.recordUserInteractionTime();
1052
- });
1053
- }
1054
- getDocumentationUrlForDiagnosticRule(rule) {
1055
- // Configuration.md is configured to have a link for every rule name.
1056
- return `https://github.com/microsoft/pyright/blob/main/docs/configuration.md#${rule}`;
1057
- }
1058
- canNavigateToFile(path, fs) {
1059
- return !fs.isInZipOrEgg(path);
1060
- }
1061
999
  }
1062
1000
  exports.LanguageServerBase = LanguageServerBase;
1063
1001
  //# sourceMappingURL=languageServerBase.js.map