@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.
- package/dist/analyzer/analyzerFileInfo.d.ts +4 -1
- package/dist/analyzer/analyzerFileInfo.js.map +1 -1
- package/dist/analyzer/backgroundAnalysisProgram.d.ts +4 -4
- package/dist/analyzer/backgroundAnalysisProgram.js +10 -7
- package/dist/analyzer/backgroundAnalysisProgram.js.map +1 -1
- package/dist/analyzer/binder.js +12 -7
- package/dist/analyzer/binder.js.map +1 -1
- package/dist/analyzer/checker.js +6 -3
- package/dist/analyzer/checker.js.map +1 -1
- package/dist/analyzer/dataClasses.js +5 -2
- package/dist/analyzer/dataClasses.js.map +1 -1
- package/dist/analyzer/declarationUtils.d.ts +6 -1
- package/dist/analyzer/declarationUtils.js +10 -8
- package/dist/analyzer/declarationUtils.js.map +1 -1
- package/dist/analyzer/importResolver.d.ts +15 -15
- package/dist/analyzer/importResolver.js +477 -477
- package/dist/analyzer/importResolver.js.map +1 -1
- package/dist/analyzer/namedTuples.d.ts +1 -1
- package/dist/analyzer/namedTuples.js +29 -41
- package/dist/analyzer/namedTuples.js.map +1 -1
- package/dist/analyzer/packageTypeReport.d.ts +2 -1
- package/dist/analyzer/packageTypeReport.js +2 -1
- package/dist/analyzer/packageTypeReport.js.map +1 -1
- package/dist/analyzer/packageTypeVerifier.d.ts +1 -1
- package/dist/analyzer/packageTypeVerifier.js +27 -13
- package/dist/analyzer/packageTypeVerifier.js.map +1 -1
- package/dist/analyzer/program.d.ts +25 -37
- package/dist/analyzer/program.js +1356 -1508
- package/dist/analyzer/program.js.map +1 -1
- package/dist/analyzer/protocols.js +1 -1
- package/dist/analyzer/protocols.js.map +1 -1
- package/dist/analyzer/service.d.ts +12 -25
- package/dist/analyzer/service.js +76 -109
- package/dist/analyzer/service.js.map +1 -1
- package/dist/analyzer/sourceFile.d.ts +6 -18
- package/dist/analyzer/sourceFile.js +57 -121
- package/dist/analyzer/sourceFile.js.map +1 -1
- package/dist/analyzer/sourceFileInfoUtils.d.ts +7 -1
- package/dist/analyzer/sourceFileInfoUtils.js.map +1 -1
- package/dist/analyzer/typeEvaluator.js +354 -322
- package/dist/analyzer/typeEvaluator.js.map +1 -1
- package/dist/analyzer/typeEvaluatorTypes.d.ts +6 -2
- package/dist/analyzer/typeGuards.js +3 -1
- package/dist/analyzer/typeGuards.js.map +1 -1
- package/dist/analyzer/typeStubWriter.js.map +1 -1
- package/dist/analyzer/typeUtils.d.ts +1 -0
- package/dist/analyzer/typeUtils.js +35 -8
- package/dist/analyzer/typeUtils.js.map +1 -1
- package/dist/backgroundAnalysisBase.d.ts +10 -11
- package/dist/backgroundAnalysisBase.js +87 -87
- package/dist/backgroundAnalysisBase.js.map +1 -1
- package/dist/commands/dumpFileDebugInfoCommand.js +8 -8
- package/dist/commands/dumpFileDebugInfoCommand.js.map +1 -1
- package/dist/commands/quickActionCommand.js +4 -1
- package/dist/commands/quickActionCommand.js.map +1 -1
- package/dist/common/cancellationUtils.d.ts +1 -1
- package/dist/common/cancellationUtils.js +9 -9
- package/dist/common/cancellationUtils.js.map +1 -1
- package/dist/common/commandLineOptions.d.ts +1 -2
- package/dist/common/commandLineOptions.js.map +1 -1
- package/dist/common/configOptions.d.ts +2 -2
- package/dist/common/configOptions.js.map +1 -1
- package/dist/common/console.d.ts +5 -9
- package/dist/common/console.js +46 -33
- package/dist/common/console.js.map +1 -1
- package/dist/common/deferred.js +10 -10
- package/dist/common/deferred.js.map +1 -1
- package/dist/common/extensibility.d.ts +26 -5
- package/dist/common/extensibility.js +1 -1
- package/dist/common/extensibility.js.map +1 -1
- package/dist/common/fileBasedCancellationUtils.js +5 -5
- package/dist/common/fileBasedCancellationUtils.js.map +1 -1
- package/dist/common/fileSystem.d.ts +12 -10
- package/dist/common/fileSystem.js.map +1 -1
- package/dist/common/fullAccessHost.d.ts +3 -3
- package/dist/common/fullAccessHost.js +6 -6
- package/dist/common/fullAccessHost.js.map +1 -1
- package/dist/common/pathUtils.d.ts +2 -2
- package/dist/common/pathUtils.js.map +1 -1
- package/dist/common/realFileSystem.js +12 -7
- package/dist/common/realFileSystem.js.map +1 -1
- package/dist/common/uriParser.d.ts +2 -2
- package/dist/common/uriParser.js +3 -3
- package/dist/common/uriParser.js.map +1 -1
- package/dist/common/workspaceEditUtils.js +7 -4
- package/dist/common/workspaceEditUtils.js.map +1 -1
- package/dist/languageServerBase.d.ts +32 -30
- package/dist/languageServerBase.js +274 -336
- package/dist/languageServerBase.js.map +1 -1
- package/dist/languageService/analyzerServiceExecutor.js +0 -1
- package/dist/languageService/analyzerServiceExecutor.js.map +1 -1
- package/dist/languageService/callHierarchyProvider.d.ts +16 -12
- package/dist/languageService/callHierarchyProvider.js +125 -41
- package/dist/languageService/callHierarchyProvider.js.map +1 -1
- package/dist/languageService/definitionProvider.d.ts +23 -9
- package/dist/languageService/definitionProvider.js +116 -91
- package/dist/languageService/definitionProvider.js.map +1 -1
- package/dist/languageService/documentHighlightProvider.d.ts +8 -3
- package/dist/languageService/documentHighlightProvider.js +17 -6
- package/dist/languageService/documentHighlightProvider.js.map +1 -1
- package/dist/languageService/documentSymbolCollector.d.ts +2 -2
- package/dist/languageService/documentSymbolCollector.js +4 -3
- package/dist/languageService/documentSymbolCollector.js.map +1 -1
- package/dist/languageService/documentSymbolProvider.js +5 -3
- package/dist/languageService/documentSymbolProvider.js.map +1 -1
- package/dist/languageService/hoverProvider.js +1 -1
- package/dist/languageService/hoverProvider.js.map +1 -1
- package/dist/languageService/insertionPointUtils.js +3 -3
- package/dist/languageService/insertionPointUtils.js.map +1 -1
- package/dist/languageService/navigationUtils.d.ts +6 -0
- package/dist/languageService/navigationUtils.js +28 -0
- package/dist/languageService/navigationUtils.js.map +1 -0
- package/dist/languageService/quickActions.d.ts +2 -2
- package/dist/languageService/quickActions.js +12 -1
- package/dist/languageService/quickActions.js.map +1 -1
- package/dist/languageService/referencesProvider.d.ts +8 -2
- package/dist/languageService/referencesProvider.js +81 -3
- package/dist/languageService/referencesProvider.js.map +1 -1
- package/dist/languageService/renameModuleProvider.d.ts +13 -13
- package/dist/languageService/renameModuleProvider.js +43 -43
- package/dist/languageService/renameModuleProvider.js.map +1 -1
- package/dist/languageService/signatureHelpProvider.d.ts +19 -23
- package/dist/languageService/signatureHelpProvider.js +111 -18
- package/dist/languageService/signatureHelpProvider.js.map +1 -1
- package/dist/parser/characterStream.d.ts +3 -3
- package/dist/parser/characterStream.js +12 -12
- package/dist/parser/characterStream.js.map +1 -1
- package/dist/parser/parser.d.ts +1 -1
- package/dist/parser/parser.js.map +1 -1
- package/dist/pyright.js +57 -54
- package/dist/pyright.js.map +1 -1
- package/dist/pyrightFileSystem.d.ts +1 -1
- package/dist/pyrightFileSystem.js +21 -21
- package/dist/pyrightFileSystem.js.map +1 -1
- package/dist/readonlyAugmentedFileSystem.d.ts +6 -6
- package/dist/readonlyAugmentedFileSystem.js +28 -28
- package/dist/readonlyAugmentedFileSystem.js.map +1 -1
- package/dist/server.js +6 -6
- package/dist/server.js.map +1 -1
- package/dist/tests/chainedSourceFiles.test.js +1 -1
- package/dist/tests/chainedSourceFiles.test.js.map +1 -1
- package/dist/tests/checker.test.js +1 -1
- package/dist/tests/harness/fourslash/testLanguageService.d.ts +3 -3
- package/dist/tests/harness/fourslash/testLanguageService.js.map +1 -1
- package/dist/tests/harness/fourslash/testState.d.ts +8 -8
- package/dist/tests/harness/fourslash/testState.js +109 -99
- package/dist/tests/harness/fourslash/testState.js.map +1 -1
- package/dist/tests/harness/vfs/filesystem.d.ts +8 -8
- package/dist/tests/harness/vfs/filesystem.js +68 -68
- package/dist/tests/harness/vfs/filesystem.js.map +1 -1
- package/dist/tests/importStatementUtils.test.js +34 -0
- package/dist/tests/importStatementUtils.test.js.map +1 -1
- package/dist/tests/moveSymbol.updateReference.test.js +14 -0
- package/dist/tests/moveSymbol.updateReference.test.js.map +1 -1
- package/dist/tests/signatureHelp.test.js +5 -1
- package/dist/tests/signatureHelp.test.js.map +1 -1
- package/dist/tests/sourceFile.test.js +1 -1
- package/dist/tests/sourceFile.test.js.map +1 -1
- package/dist/tests/testStateUtils.js +1 -1
- package/dist/tests/testStateUtils.js.map +1 -1
- package/dist/tests/typeEvaluator1.test.js +8 -0
- package/dist/tests/typeEvaluator1.test.js.map +1 -1
- package/dist/tests/typeEvaluator2.test.js +12 -0
- package/dist/tests/typeEvaluator2.test.js.map +1 -1
- package/dist/tests/typeEvaluator3.test.js +1 -1
- 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(
|
108
|
+
constructor(serverOptions, connection, console, uriParserFactory = (fs) => new uriParser_1.UriParser(fs)) {
|
103
109
|
var _a, _b;
|
104
|
-
this.
|
105
|
-
this.
|
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 =
|
137
|
-
this.console.info(`${
|
138
|
-
this.console.info(`Server root directory: ${
|
139
|
-
this.
|
140
|
-
this.
|
141
|
-
this.
|
142
|
-
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.
|
153
|
+
const moduleDirectory = this.fs.getModulePath();
|
147
154
|
if (moduleDirectory) {
|
148
|
-
this.
|
155
|
+
this.fs.chdir(moduleDirectory);
|
149
156
|
}
|
150
157
|
// Set up callbacks.
|
151
|
-
this.setupConnection((_a =
|
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.
|
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.
|
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.
|
274
|
+
return this.connection.workspace.getConfiguration(item);
|
178
275
|
}
|
179
|
-
if (this.
|
180
|
-
return (0, collectionUtils_1.getNestedProperty)(this.
|
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.
|
263
|
-
this.
|
264
|
-
this.
|
265
|
-
this.
|
266
|
-
this.
|
267
|
-
this.
|
268
|
-
this.
|
269
|
-
this.
|
270
|
-
this.
|
271
|
-
this.
|
272
|
-
this.
|
273
|
-
this.
|
274
|
-
this.
|
275
|
-
this.
|
276
|
-
this.
|
277
|
-
this.
|
278
|
-
this.
|
279
|
-
const callHierarchy = this.
|
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.
|
284
|
-
this.
|
285
|
-
this.
|
286
|
-
this.
|
287
|
-
this.
|
288
|
-
this.
|
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.
|
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.
|
386
|
-
this.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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
|
-
|
473
|
-
return
|
474
|
-
|
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.
|
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.
|
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.
|
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.
|
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.
|
532
|
+
const { filePath, position } = this.uriParser.decodeTextDocumentPosition(params.textDocument, params.position);
|
525
533
|
const workspace = await this.getWorkspaceForFile(filePath);
|
526
|
-
return workspace.service.
|
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
|
-
|
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
|
-
|
536
|
-
|
537
|
-
|
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.
|
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.
|
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.
|
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.
|
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.
|
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
|
-
|
688
|
-
|
689
|
-
|
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.
|
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
|
-
|
705
|
-
|
706
|
-
|
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.
|
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
|
-
|
722
|
-
|
723
|
-
|
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.
|
734
|
-
if (!this.
|
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.
|
747
|
-
if (!this.
|
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,
|
692
|
+
w.service.updateOpenFileContents(filePath, params.textDocument.version, newContents, ipythonMode);
|
755
693
|
});
|
756
694
|
}
|
757
695
|
async onDidCloseTextDocument(params) {
|
758
|
-
const filePath = this.
|
759
|
-
if (!this.
|
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.
|
710
|
+
const filePath = this.fs.realCasePath(this.uriParser.decodeTextDocumentUri(change.uri));
|
772
711
|
const eventType = change.type === 1 ? 'add' : 'change';
|
773
|
-
this.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
908
|
+
return { reporter: reporter, source: (0, cancellationUtils_1.CancelAfter)(this.serverOptions.cancellationProvider, token) };
|
956
909
|
}
|
957
|
-
const serverInitiatedReporter = await this.
|
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.
|
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.
|
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
|