mirror of
https://github.com/microsoft/pyright.git
synced 2025-12-23 09:19:29 +00:00
Pull Pylance with Pyright 1.1.406 (#11010)
Some checks failed
Run mypy_primer on push / Run mypy_primer on push (push) Has been cancelled
Validation / Typecheck (push) Has been cancelled
Validation / Style (push) Has been cancelled
Validation / Test macos-latest (push) Has been cancelled
Validation / Test ubuntu-latest (push) Has been cancelled
Validation / Test windows-latest (push) Has been cancelled
Validation / Build (push) Has been cancelled
Validation / Required (push) Has been cancelled
Some checks failed
Run mypy_primer on push / Run mypy_primer on push (push) Has been cancelled
Validation / Typecheck (push) Has been cancelled
Validation / Style (push) Has been cancelled
Validation / Test macos-latest (push) Has been cancelled
Validation / Test ubuntu-latest (push) Has been cancelled
Validation / Test windows-latest (push) Has been cancelled
Validation / Build (push) Has been cancelled
Validation / Required (push) Has been cancelled
* pull-pylance-with-pyright-1.1.406-20251008-232729 * fixed linting issue --------- Co-authored-by: Azure Piplines <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: HeeJae Chang <hechang@microsoft.com>
This commit is contained in:
parent
9ed33cf7be
commit
20aa20a100
27 changed files with 368 additions and 132 deletions
|
|
@ -88,10 +88,10 @@ export interface AnalyzerServiceOptions {
|
|||
serviceId?: string;
|
||||
skipScanningUserFiles?: boolean;
|
||||
fileSystem?: FileSystem;
|
||||
usingPullDiagnostics?: boolean;
|
||||
onInvalidated?: (reason: InvalidatedReason) => void;
|
||||
// Optional callback fired once when initial source file enumeration completes.
|
||||
onSourceEnumerationComplete?: () => void;
|
||||
shouldRunAnalysis: () => boolean;
|
||||
}
|
||||
|
||||
interface ConfigFileContents {
|
||||
|
|
@ -214,6 +214,10 @@ export class AnalyzerService {
|
|||
return this.options.serviceId!;
|
||||
}
|
||||
|
||||
get checkOnlyOpenFiles() {
|
||||
return !!this._commandLineOptions?.languageServerSettings.checkOnlyOpenFiles;
|
||||
}
|
||||
|
||||
setServiceName(instanceName: string) {
|
||||
this._instanceName = instanceName;
|
||||
}
|
||||
|
|
@ -230,7 +234,6 @@ export class AnalyzerService {
|
|||
backgroundAnalysis,
|
||||
skipScanningUserFiles: true,
|
||||
fileSystem,
|
||||
usingPullDiagnostics: this.options.usingPullDiagnostics,
|
||||
});
|
||||
|
||||
// Cloned service will use whatever user files the service currently has.
|
||||
|
|
@ -492,6 +495,11 @@ export class AnalyzerService {
|
|||
);
|
||||
}
|
||||
|
||||
invalidateAndScheduleReanalysis(reason: InvalidatedReason) {
|
||||
this.invalidateAndForceReanalysis(reason);
|
||||
this.scheduleReanalysis(/* requireTrackedFileUpdate */ false);
|
||||
}
|
||||
|
||||
invalidateAndForceReanalysis(reason: InvalidatedReason) {
|
||||
if (this.options.onInvalidated) {
|
||||
this.options.onInvalidated(reason);
|
||||
|
|
@ -566,13 +574,17 @@ export class AnalyzerService {
|
|||
}
|
||||
|
||||
protected runAnalysis(token: CancellationToken) {
|
||||
// In pull diagnostics mode, the service doesn't perform analysis on its own.
|
||||
// Instead the client deliberately asks for diagnostics on a file-by-file basis.
|
||||
if (!this.options.usingPullDiagnostics) {
|
||||
// Double check we're allowed to run analysis now. We might be in pull mode or
|
||||
// we might not have a workspace response callback. The creation of the workspace
|
||||
// callback will cause this to rerun, so no need to start polling.
|
||||
if (this.options.shouldRunAnalysis()) {
|
||||
const moreToAnalyze = this._backgroundAnalysisProgram.startAnalysis(token);
|
||||
if (moreToAnalyze) {
|
||||
this.scheduleReanalysis(/* requireTrackedFileUpdate */ false);
|
||||
}
|
||||
} else if (this.options.onInvalidated) {
|
||||
// Just cause a refresh.
|
||||
this.options.onInvalidated(InvalidatedReason.Reanalyzed);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -190,14 +190,15 @@ export class FullAccessHost extends LimitedAccessHost {
|
|||
code: string,
|
||||
args: string[],
|
||||
cwd: Uri,
|
||||
token: CancellationToken
|
||||
token: CancellationToken,
|
||||
forceIsolated: boolean = false
|
||||
): Promise<ScriptOutput> {
|
||||
// If it is already cancelled, don't bother to run snippet.
|
||||
throwIfCancellationRequested(token);
|
||||
|
||||
// What to do about conda here?
|
||||
return new Promise<ScriptOutput>((resolve, reject) => {
|
||||
const commandLineArgs = ['-c', code, ...args];
|
||||
const commandLineArgs = forceIsolated ? ['-I', '-c', code, ...args] : ['-c', code, ...args];
|
||||
|
||||
const child = this._executePythonInterpreter(pythonPath?.getFilePath(), (p) =>
|
||||
child_process.spawn(p, commandLineArgs, {
|
||||
|
|
|
|||
|
|
@ -46,7 +46,8 @@ export interface Host {
|
|||
code: string,
|
||||
args: string[],
|
||||
cwd: Uri,
|
||||
token: CancellationToken
|
||||
token: CancellationToken,
|
||||
forceIsolated?: boolean
|
||||
): Promise<ScriptOutput>;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,8 @@ import {
|
|||
TextDocumentSyncKind,
|
||||
WorkDoneProgressReporter,
|
||||
WorkspaceDiagnosticParams,
|
||||
WorkspaceDocumentDiagnosticReport,
|
||||
WorkspaceDiagnosticReport,
|
||||
WorkspaceDiagnosticReportPartialResult,
|
||||
WorkspaceEdit,
|
||||
WorkspaceFoldersChangeEvent,
|
||||
WorkspaceSymbol,
|
||||
|
|
@ -82,7 +83,7 @@ import { BackgroundAnalysisProgram, InvalidatedReason } from './analyzer/backgro
|
|||
import { ImportResolver } from './analyzer/importResolver';
|
||||
import { MaxAnalysisTime } from './analyzer/program';
|
||||
import { AnalyzerService, LibraryReanalysisTimeProvider, getNextServiceId } from './analyzer/service';
|
||||
import { IPythonMode, SourceFile } from './analyzer/sourceFile';
|
||||
import { IPythonMode } from './analyzer/sourceFile';
|
||||
import type { IBackgroundAnalysis } from './backgroundAnalysisBase';
|
||||
import { CommandResult } from './commands/commandResult';
|
||||
import { CancelAfter } from './common/cancellationUtils';
|
||||
|
|
@ -136,9 +137,33 @@ import {
|
|||
Workspace,
|
||||
WorkspaceFactory,
|
||||
} from './workspaceFactory';
|
||||
import { PullDiagnosticsDynamicFeature } from './languageService/pullDiagnosticsDynamicFeature';
|
||||
|
||||
const UncomputedDiagnosticsVersion = -1;
|
||||
|
||||
export function wrapProgressReporter(reporter: WorkDoneProgressReporter): ProgressReporter {
|
||||
let isDisplayingProgress = false;
|
||||
return {
|
||||
isDisplayingProgress: () => {
|
||||
return isDisplayingProgress;
|
||||
},
|
||||
isEnabled: () => {
|
||||
return true;
|
||||
},
|
||||
begin: () => {
|
||||
isDisplayingProgress = true;
|
||||
reporter.begin('', /* percentage */ undefined, /* message */ undefined, /* cancellable */ false);
|
||||
},
|
||||
report: (message) => {
|
||||
reporter.report(message);
|
||||
},
|
||||
end: () => {
|
||||
isDisplayingProgress = false;
|
||||
reporter.done();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export abstract class LanguageServerBase implements LanguageServerInterface, Disposable {
|
||||
// We support running only one "find all reference" at a time.
|
||||
private _pendingFindAllRefsCancellationSource: AbstractCancellationTokenSource | undefined;
|
||||
|
|
@ -153,6 +178,9 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
|
|||
|
||||
private _initialized = false;
|
||||
private _workspaceFoldersChangedDisposable: Disposable | undefined;
|
||||
private _workspaceDiagnosticsReporter: ResultProgressReporter<WorkspaceDiagnosticReportPartialResult> | undefined;
|
||||
private _workspaceDiagnosticsProgressReporter: ProgressReporter | undefined;
|
||||
private _workspaceDiagnosticsResolve: ((value: WorkspaceDiagnosticReport) => void) | undefined;
|
||||
|
||||
protected client: ClientCapabilities = {
|
||||
hasConfigurationCapability: false,
|
||||
|
|
@ -278,12 +306,20 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
|
|||
libraryReanalysisTimeProvider,
|
||||
serviceId,
|
||||
fileSystem: services?.fs ?? this.serverOptions.serviceProvider.fs(),
|
||||
usingPullDiagnostics: this.client.supportsPullDiagnostics,
|
||||
onInvalidated: (reason) => {
|
||||
if (this.client.supportsPullDiagnostics) {
|
||||
this.connection.sendRequest(DiagnosticRefreshRequest.type);
|
||||
// If we're in openFilesOnly mode and the client supports pull diagnostics, request a refresh. In
|
||||
// workspace mode we just use the 'push' notification to respond to the workspace diagnostics
|
||||
if (this.client.supportsPullDiagnostics && service.checkOnlyOpenFiles) {
|
||||
void this.connection.sendRequest(DiagnosticRefreshRequest.type);
|
||||
}
|
||||
},
|
||||
shouldRunAnalysis: () => {
|
||||
// We should run analysis if:
|
||||
// The client doesn't support pull diagnostics (meaning we have to run analysis ourselves)
|
||||
// or
|
||||
// We have a workspace partial result callback (meaning in pull mode, we're waiting for workspace results)
|
||||
return !this.client.supportsPullDiagnostics || this._workspaceDiagnosticsReporter !== undefined;
|
||||
},
|
||||
});
|
||||
|
||||
service.setCompletionCallback((results) => this.onAnalysisCompletedHandler(service.fs, results));
|
||||
|
|
@ -350,6 +386,12 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
|
|||
|
||||
this.dynamicFeatures.update(serverSettings);
|
||||
|
||||
// If the workspace mode has changed, we may need to resolve the workspace diagnostics promise.
|
||||
if (serverSettings.openFilesOnly && this._workspaceDiagnosticsResolve) {
|
||||
this._workspaceDiagnosticsResolve({ items: [] });
|
||||
this._workspaceDiagnosticsResolve = undefined;
|
||||
}
|
||||
|
||||
// Then use the updated settings to restart the service.
|
||||
this.updateOptionsAndRestartService(workspace, serverSettings);
|
||||
|
||||
|
|
@ -510,8 +552,8 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
|
|||
this.connection.onDidChangeWatchedFiles((params) => this.onDidChangeWatchedFiles(params));
|
||||
|
||||
this.connection.languages.diagnostics.on(async (params, token) => this.onDiagnostics(params, token));
|
||||
this.connection.languages.diagnostics.onWorkspace(async (params, token) =>
|
||||
this.onWorkspaceDiagnostics(params, token)
|
||||
this.connection.languages.diagnostics.onWorkspace(async (params, token, progress, reporter) =>
|
||||
this.onWorkspaceDiagnostics(params, token, progress, reporter)
|
||||
);
|
||||
this.connection.onExecuteCommand(async (params, token, reporter) =>
|
||||
this.onExecuteCommand(params, token, reporter)
|
||||
|
|
@ -575,11 +617,9 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
|
|||
);
|
||||
this.client.supportsPullDiagnostics =
|
||||
!!capabilities.textDocument?.diagnostic?.dynamicRegistration &&
|
||||
initializationOptions?.diagnosticMode !== 'workspace' &&
|
||||
initializationOptions?.disablePullDiagnostics !== true;
|
||||
this.client.requiresPullRelatedInformationCapability =
|
||||
!!capabilities.textDocument?.diagnostic?.relatedInformation &&
|
||||
initializationOptions?.diagnosticMode !== 'workspace' &&
|
||||
initializationOptions?.disablePullDiagnostics !== true;
|
||||
|
||||
// Create a service instance for each of the workspace folders.
|
||||
|
|
@ -641,12 +681,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
|
|||
};
|
||||
|
||||
if (this.client.supportsPullDiagnostics) {
|
||||
result.capabilities.diagnosticProvider = {
|
||||
identifier: 'pyright',
|
||||
documentSelector: null,
|
||||
interFileDependencies: true,
|
||||
workspaceDiagnostics: false, // Workspace wide are not pull diagnostics.
|
||||
};
|
||||
this.addDynamicFeature(new PullDiagnosticsDynamicFeature(this.connection, this.serverOptions.productName));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -1177,23 +1212,33 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
|
|||
return result;
|
||||
}
|
||||
|
||||
protected async onWorkspaceDiagnostics(params: WorkspaceDiagnosticParams, token: CancellationToken) {
|
||||
const workspaces = await this.getWorkspaces();
|
||||
const promises: Promise<WorkspaceDocumentDiagnosticReport>[] = [];
|
||||
workspaces.forEach((workspace) => {
|
||||
if (!workspace.disableLanguageServices) {
|
||||
const files = workspace.service.getOwnedFiles();
|
||||
files.forEach((file) => {
|
||||
const sourceFile = workspace.service.getSourceFile(file)!;
|
||||
if (canNavigateToFile(workspace.service.fs, sourceFile.getUri())) {
|
||||
promises.push(this._getWorkspaceDocumentDiagnostics(params, sourceFile, workspace, token));
|
||||
}
|
||||
});
|
||||
}
|
||||
protected async onWorkspaceDiagnostics(
|
||||
params: WorkspaceDiagnosticParams,
|
||||
token: CancellationToken,
|
||||
workDoneProgress: WorkDoneProgressReporter,
|
||||
resultReporter?: ResultProgressReporter<WorkspaceDiagnosticReportPartialResult>
|
||||
) {
|
||||
// Resolve any pending workspace diagnostics. We only allow one at a time.
|
||||
this._workspaceDiagnosticsResolve?.({ items: [] });
|
||||
this._workspaceDiagnosticsResolve = undefined;
|
||||
|
||||
// Save the progress reporters and force a refresh of analysis.
|
||||
this._workspaceDiagnosticsProgressReporter = !isNullProgressReporter(workDoneProgress)
|
||||
? wrapProgressReporter(workDoneProgress)
|
||||
: undefined;
|
||||
this._workspaceDiagnosticsReporter = resultReporter;
|
||||
this.workspaceFactory.getNonDefaultWorkspaces().forEach((workspace) => {
|
||||
workspace.service.invalidateAndScheduleReanalysis(InvalidatedReason.Reanalyzed);
|
||||
});
|
||||
|
||||
return new Promise<WorkspaceDiagnosticReport>((resolve, reject) => {
|
||||
// We never resolve as this should be a continually occurring process. Scheduling analysis
|
||||
// should cause a new workspace diagnostic to be generated.
|
||||
|
||||
// Save the resolve callback to be used during shutdown so that tests don't crash
|
||||
// on the unresolved promise for the workspace diagnostics.
|
||||
this._workspaceDiagnosticsResolve = resolve;
|
||||
});
|
||||
return {
|
||||
items: await Promise.all(promises),
|
||||
};
|
||||
}
|
||||
|
||||
protected onDidChangeWatchedFiles(params: DidChangeWatchedFilesParams) {
|
||||
|
|
@ -1262,6 +1307,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
|
|||
|
||||
protected onShutdown(token: CancellationToken) {
|
||||
// Shutdown remaining workspaces.
|
||||
this._workspaceDiagnosticsResolve?.({ items: [] });
|
||||
this.workspaceFactory.clear();
|
||||
|
||||
// Stop tracking all open files.
|
||||
|
|
@ -1286,11 +1332,6 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
|
|||
}
|
||||
|
||||
protected onAnalysisCompletedHandler(fs: FileSystem, results: AnalysisResults): void {
|
||||
// If we're in pull mode, disregard any 'tracking' results. They're not necessary.
|
||||
if (this.client.supportsPullDiagnostics && results.reason === 'tracking') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send the computed diagnostics to the client.
|
||||
results.diagnostics.forEach((fileDiag) => {
|
||||
if (!this.canNavigateToFile(fileDiag.fileUri, fs)) {
|
||||
|
|
@ -1300,17 +1341,18 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
|
|||
this.sendDiagnostics(this.convertDiagnostics(fs, fileDiag));
|
||||
});
|
||||
|
||||
if (!this._progressReporter.isEnabled(results)) {
|
||||
const reporter = this.getAnalysisProgressReporter();
|
||||
if (!reporter.isEnabled(results)) {
|
||||
// Make sure to disable progress bar if it is currently active.
|
||||
// This can happen if a user changes typeCheckingMode in the middle
|
||||
// of analysis.
|
||||
// end() is noop if there is no active progress bar.
|
||||
this._progressReporter.end();
|
||||
reporter.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// Update progress.
|
||||
this.sendProgressMessage(results.requiringAnalysisCount.files);
|
||||
this.sendProgressMessage(results.requiringAnalysisCount.files, results.requiringAnalysisCount.cells);
|
||||
}
|
||||
|
||||
protected incrementAnalysisProgress() {
|
||||
|
|
@ -1326,9 +1368,17 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
|
|||
this.sendProgressMessage(this._progressReportCounter);
|
||||
}
|
||||
|
||||
protected sendProgressMessage(fileCount: number) {
|
||||
protected getAnalysisProgressReporter(): ProgressReporter {
|
||||
if (this._workspaceDiagnosticsProgressReporter) {
|
||||
return this._workspaceDiagnosticsProgressReporter;
|
||||
}
|
||||
return this._progressReporter;
|
||||
}
|
||||
|
||||
protected sendProgressMessage(fileCount: number, cellCount?: number) {
|
||||
const reporter = this.getAnalysisProgressReporter();
|
||||
if (fileCount <= 0) {
|
||||
this._progressReporter.end();
|
||||
reporter.end();
|
||||
return;
|
||||
}
|
||||
const progressMessage =
|
||||
|
|
@ -1339,10 +1389,10 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
|
|||
});
|
||||
|
||||
// Update progress.
|
||||
if (!this._progressReporter.isDisplayingProgress()) {
|
||||
this._progressReporter.begin();
|
||||
if (!reporter.isDisplayingProgress()) {
|
||||
reporter.begin();
|
||||
}
|
||||
this._progressReporter.report(progressMessage);
|
||||
reporter.report(progressMessage);
|
||||
}
|
||||
|
||||
protected onWorkspaceCreated(workspace: Workspace) {
|
||||
|
|
@ -1442,7 +1492,16 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
|
|||
} else {
|
||||
this.documentsWithDiagnostics.add(param.uri);
|
||||
}
|
||||
this.connection.sendDiagnostics(param);
|
||||
// If we're waiting for a pending workspace diagnostic, send a partial result.
|
||||
if (this._workspaceDiagnosticsReporter) {
|
||||
// Skip storing previous result ids, just send new results every time.
|
||||
this._workspaceDiagnosticsReporter.report({
|
||||
items: [{ ...param, kind: 'full', version: param.version || null, items: param.diagnostics }],
|
||||
});
|
||||
} else {
|
||||
// Otherwise send a publish diagnostic notification.
|
||||
this.connection.sendDiagnostics(param);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1465,33 +1524,6 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
|
|||
|
||||
return MarkupKind.PlainText;
|
||||
}
|
||||
private async _getWorkspaceDocumentDiagnostics(
|
||||
params: WorkspaceDiagnosticParams,
|
||||
sourceFile: SourceFile,
|
||||
workspace: Workspace,
|
||||
token: CancellationToken
|
||||
) {
|
||||
const originalUri = workspace.service.fs.getOriginalUri(sourceFile.getUri());
|
||||
const result: WorkspaceDocumentDiagnosticReport = {
|
||||
uri: originalUri.toString(),
|
||||
version: sourceFile.getClientVersion() ?? null,
|
||||
kind: 'full',
|
||||
items: [],
|
||||
};
|
||||
const previousId = params.previousResultIds.find((x) => x.uri === originalUri.toString());
|
||||
const documentResult = await this.onDiagnostics(
|
||||
{ previousResultId: previousId?.value, textDocument: { uri: result.uri } },
|
||||
token
|
||||
);
|
||||
if (documentResult.kind === 'full') {
|
||||
result.items = documentResult.items;
|
||||
} else {
|
||||
(result as any).kind = documentResult.kind;
|
||||
delete (result as any).items;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private _convertDiagnostics(fs: FileSystem, diags: AnalyzerDiagnostic[]): Diagnostic[] {
|
||||
const convertedDiags: Diagnostic[] = [];
|
||||
|
||||
|
|
@ -1501,12 +1533,19 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
|
|||
const code = this.getDiagCode(diag, rule);
|
||||
const vsDiag = Diagnostic.create(diag.range, diag.message, severity, code, this.serverOptions.productName);
|
||||
|
||||
// Save all of the actions in the data.
|
||||
const actions = diag.getActions();
|
||||
if (actions?.length) {
|
||||
vsDiag.data = { ...vsDiag.data, actions: actions };
|
||||
}
|
||||
|
||||
if (
|
||||
diag.category === DiagnosticCategory.UnusedCode ||
|
||||
diag.category === DiagnosticCategory.UnreachableCode
|
||||
) {
|
||||
vsDiag.tags = [DiagnosticTag.Unnecessary];
|
||||
vsDiag.severity = DiagnosticSeverity.Hint;
|
||||
vsDiag.data = { ...vsDiag.data, category: diag.category, rule: rule };
|
||||
|
||||
// If the client doesn't support "unnecessary" tags, don't report unused code.
|
||||
if (!this.client.supportsUnnecessaryDiagnosticTag) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* PullDiagnosticsDynamicFeature.ts
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* implementation of pull mode diagnostics feature registration
|
||||
*/
|
||||
import {
|
||||
Connection,
|
||||
DiagnosticRegistrationOptions,
|
||||
Disposable,
|
||||
DocumentDiagnosticRequest,
|
||||
} from 'vscode-languageserver';
|
||||
import { DynamicFeature } from './dynamicFeature';
|
||||
import { ServerSettings } from '../common/languageServerInterface';
|
||||
|
||||
export class PullDiagnosticsDynamicFeature extends DynamicFeature {
|
||||
private _workspaceSupport = false;
|
||||
private _registered = false;
|
||||
|
||||
constructor(private readonly _connection: Connection, private readonly _id: string = 'pyright') {
|
||||
super('pull diagnostics');
|
||||
}
|
||||
|
||||
override update(settings: ServerSettings): void {
|
||||
// There is one caveat with these settings. These settings can be set
|
||||
// per workspace, but these features apply to the entire language server.
|
||||
// Therefore, if the user has set these settings differently per workspace,
|
||||
// the last setting will take precedence.
|
||||
const workspaceSupport = settings.openFilesOnly === false;
|
||||
if (this._workspaceSupport !== workspaceSupport || !this._registered) {
|
||||
this._workspaceSupport = workspaceSupport;
|
||||
this.register();
|
||||
}
|
||||
}
|
||||
|
||||
protected override registerFeature(): Promise<Disposable> {
|
||||
this._registered = true;
|
||||
const options: DiagnosticRegistrationOptions = {
|
||||
interFileDependencies: true,
|
||||
workspaceDiagnostics: this._workspaceSupport,
|
||||
documentSelector: null,
|
||||
identifier: this._id,
|
||||
};
|
||||
return this._connection.client.register(DocumentDiagnosticRequest.type, options);
|
||||
}
|
||||
}
|
||||
|
|
@ -580,6 +580,7 @@
|
|||
"typedDictBaseClass": "Všechny základní třídy pro třídy TypedDict musí být také třídami TypedDict",
|
||||
"typedDictBoolParam": "Očekávalo se, že parametr {name} bude mít hodnotu True nebo False",
|
||||
"typedDictClosedExtras": "Základní \"{name}\" třídy je TypedDict, který omezuje typ dalších položek na typ \"{type}\"",
|
||||
"typedDictClosedFalseNonOpenBase": "Base class \"{name}\" is not an open TypedDict; closed=False is not allowed",
|
||||
"typedDictClosedNoExtras": "Základní třída {name} je closed TypedDict; položky navíc nejsou povolené.",
|
||||
"typedDictDelete": "Nepovedlo se odstranit položku v TypedDict",
|
||||
"typedDictEmptyName": "Názvy v rámci TypedDict nemůžou být prázdné",
|
||||
|
|
@ -605,6 +606,7 @@
|
|||
"unannotatedFunctionSkipped": "Analýza funkce „{name}“ se přeskočila, protože není označená",
|
||||
"unaryOperationNotAllowed": "Ve výrazu typu není povolený unární operátor.",
|
||||
"unexpectedAsyncToken": "Očekávalo se, že za async bude následovat def, with nebo for",
|
||||
"unexpectedEof": "Unexpected EOF",
|
||||
"unexpectedExprToken": "Neočekávaný token na konci výrazu",
|
||||
"unexpectedIndent": "Neočekávané odsazení",
|
||||
"unexpectedUnindent": "Neočekává se unindent",
|
||||
|
|
@ -741,7 +743,7 @@
|
|||
"namedTupleNotAllowed": "NamedTuple se nedá použít pro kontroly instancí nebo tříd.",
|
||||
"newMethodLocation": "Metoda __new__ je definována ve třídě {type}",
|
||||
"newMethodSignature": "Podpis __new__ je {type}",
|
||||
"newTypeClassNotAllowed": "Třídu vytvořenou pomocí NewType nelze použít s kontrolami instancí a tříd.",
|
||||
"newTypeClassNotAllowed": "Type created with NewType cannot be used with instance and class checks",
|
||||
"noOverloadAssignable": "Typ {type} neodpovídá žádné přetížené funkci",
|
||||
"noneNotAllowed": "Možnost None se nedá použít pro kontroly instancí nebo tříd.",
|
||||
"orPatternMissingName": "Chybějící názvy: {name}",
|
||||
|
|
|
|||
|
|
@ -580,6 +580,7 @@
|
|||
"typedDictBaseClass": "Alle Basisklassen für TypedDict-Klassen müssen auch TypedDict-Klassen sein.",
|
||||
"typedDictBoolParam": "Es wird erwartet, dass \"{name}\" Parameter den Wert \"True\" oder \"False\" aufweist.",
|
||||
"typedDictClosedExtras": "Die Basisklasse \"{name}\" ist eine TypedDict, die den Typ zusätzlicher Elemente auf den Typ \"{type}\" beschränkt.",
|
||||
"typedDictClosedFalseNonOpenBase": "Base class \"{name}\" is not an open TypedDict; closed=False is not allowed",
|
||||
"typedDictClosedNoExtras": "Die Basisklasse „{name}“ ist ein closed TypedDict; zusätzliche Elemente sind nicht zulässig.",
|
||||
"typedDictDelete": "Das Element in TypedDict konnte nicht gelöscht werden.",
|
||||
"typedDictEmptyName": "Namen innerhalb eines TypedDict dürfen nicht leer sein.",
|
||||
|
|
@ -605,6 +606,7 @@
|
|||
"unannotatedFunctionSkipped": "Die Analyse der Funktion \"{name}\" wird übersprungen, da sie nicht kommentiert wurde.",
|
||||
"unaryOperationNotAllowed": "Der unäre Operator ist im Typausdruck nicht zulässig",
|
||||
"unexpectedAsyncToken": "Es wurde erwartet, dass \"def\", \"with\" oder \"for\" auf \"async\" folgt.",
|
||||
"unexpectedEof": "Unexpected EOF",
|
||||
"unexpectedExprToken": "Unerwartetes Token am Ende des Ausdrucks.",
|
||||
"unexpectedIndent": "Unerwarteter Einzug",
|
||||
"unexpectedUnindent": "\"Unindent\" nicht erwartet.",
|
||||
|
|
@ -741,7 +743,7 @@
|
|||
"namedTupleNotAllowed": "NamedTuple kann nicht für Instanzen- oder Klassenüberprüfungen verwendet werden.",
|
||||
"newMethodLocation": "Die __new__ Methode ist in der Klasse \"{type}\" definiert.",
|
||||
"newMethodSignature": "Signatur von __new__ ist \"{type}\"",
|
||||
"newTypeClassNotAllowed": "Die mit NewType erstellte Klasse kann nicht mit Instanz- und Klassenüberprüfungen verwendet werden.",
|
||||
"newTypeClassNotAllowed": "Type created with NewType cannot be used with instance and class checks",
|
||||
"noOverloadAssignable": "Keine überladene Funktion stimmt mit dem Typ \"{type}\" überein.",
|
||||
"noneNotAllowed": "\"None\" kann nicht für Instanz- oder Klassenprüfungen verwendet werden.",
|
||||
"orPatternMissingName": "Fehlende Namen: {name}",
|
||||
|
|
|
|||
|
|
@ -580,6 +580,7 @@
|
|||
"typedDictBaseClass": "Todas las clases base de las clases TypedDict deben ser también clases TypedDict",
|
||||
"typedDictBoolParam": "Se esperaba que el parámetro \"{name}\" tuviera un valor de True o False.",
|
||||
"typedDictClosedExtras": "El \"{name}\" de clase base es un TypedDict que limita el tipo de elementos adicionales al tipo \"{type}\"",
|
||||
"typedDictClosedFalseNonOpenBase": "Base class \"{name}\" is not an open TypedDict; closed=False is not allowed",
|
||||
"typedDictClosedNoExtras": "La clase base \"{name}\" es un TypedDict closed; no se permiten elementos adicionales",
|
||||
"typedDictDelete": "No se puede eliminar un elemento en TypedDict",
|
||||
"typedDictEmptyName": "Los nombres de un TypedDict no pueden estar vacíos",
|
||||
|
|
@ -605,6 +606,7 @@
|
|||
"unannotatedFunctionSkipped": "Se omite el análisis de la función \"{name}\" porque no está anotada",
|
||||
"unaryOperationNotAllowed": "Operador unario no permitido en la expresión de tipo",
|
||||
"unexpectedAsyncToken": "Se esperaba que \"def\", \"with\" o \"for\" siguieran a \"async\".",
|
||||
"unexpectedEof": "Unexpected EOF",
|
||||
"unexpectedExprToken": "Token inesperado al final de la expresión",
|
||||
"unexpectedIndent": "sangSangría inesperadaría inesperada",
|
||||
"unexpectedUnindent": "No se espera sangría",
|
||||
|
|
@ -741,7 +743,7 @@
|
|||
"namedTupleNotAllowed": "No se puede usar NamedTuple para comprobaciones de instancia o clase",
|
||||
"newMethodLocation": "El método __new__ está definido en la clase \"{type}\"",
|
||||
"newMethodSignature": "La firma de __new__ es \"{type}\"",
|
||||
"newTypeClassNotAllowed": "La clase creada con NewType no se puede usar con comprobaciones de instancia y clase",
|
||||
"newTypeClassNotAllowed": "Type created with NewType cannot be used with instance and class checks",
|
||||
"noOverloadAssignable": "Ninguna función sobrecargada coincide con el tipo \"{type}\"",
|
||||
"noneNotAllowed": "No se puede usar None para comprobaciones de instancia o clase",
|
||||
"orPatternMissingName": "Nombres que faltan: {name}",
|
||||
|
|
|
|||
|
|
@ -580,6 +580,7 @@
|
|||
"typedDictBaseClass": "Toutes les classes de base pour les classes TypedDict doivent également être des classes TypedDict",
|
||||
"typedDictBoolParam": "Paramètre « {name} » attendu avec la valeur True ou False",
|
||||
"typedDictClosedExtras": "Le \"{name}\" de classe de base est un TypedDict qui limite le type d’éléments supplémentaires au type \"{type}\"",
|
||||
"typedDictClosedFalseNonOpenBase": "Base class \"{name}\" is not an open TypedDict; closed=False is not allowed",
|
||||
"typedDictClosedNoExtras": "La classe de base « {name} » est un TypedDict closed, les éléments supplémentaires ne sont pas autorisés",
|
||||
"typedDictDelete": "Impossible de supprimer l’élément dans TypedDict",
|
||||
"typedDictEmptyName": "Les noms dans un TypedDict ne peuvent pas être vides",
|
||||
|
|
@ -605,6 +606,7 @@
|
|||
"unannotatedFunctionSkipped": "L'analyse de la fonction \"{name}\" est ignorée car elle n'est pas annotée",
|
||||
"unaryOperationNotAllowed": "L'opérateur unaire n'est pas autorisé dans l'expression de type",
|
||||
"unexpectedAsyncToken": "« def », « with » ou « for » attendu pour suivre « async »",
|
||||
"unexpectedEof": "Unexpected EOF",
|
||||
"unexpectedExprToken": "Jeton inattendu à la fin de l’expression",
|
||||
"unexpectedIndent": "Retrait inattendu",
|
||||
"unexpectedUnindent": "Unindent non attendu",
|
||||
|
|
@ -741,7 +743,7 @@
|
|||
"namedTupleNotAllowed": "NamedTuple ne peut pas être utilisé pour les vérifications d’instance ou de classe",
|
||||
"newMethodLocation": "La méthode __new__ est définie dans la classe « {type} »",
|
||||
"newMethodSignature": "La signature de __new__ est « {type} »",
|
||||
"newTypeClassNotAllowed": "La classe créée avec NewType ne peut pas être utilisée avec des vérifications de instance et de classe",
|
||||
"newTypeClassNotAllowed": "Type created with NewType cannot be used with instance and class checks",
|
||||
"noOverloadAssignable": "Aucune fonction surchargée ne correspond au type « {type} »",
|
||||
"noneNotAllowed": "None ne peut être utilisé pour les vérifications de instance ou de classe",
|
||||
"orPatternMissingName": "Noms manquants : {name}",
|
||||
|
|
|
|||
|
|
@ -580,6 +580,7 @@
|
|||
"typedDictBaseClass": "Anche tutte le classi di base per le classi TypedDict devono essere classi TypedDict",
|
||||
"typedDictBoolParam": "È previsto che il parametro \"{name}\" abbia il valore True o False",
|
||||
"typedDictClosedExtras": "La classe di base \"{name}\" è una TypedDict che limita il tipo di elementi aggiuntivi al tipo \"{type}\"",
|
||||
"typedDictClosedFalseNonOpenBase": "Base class \"{name}\" is not an open TypedDict; closed=False is not allowed",
|
||||
"typedDictClosedNoExtras": "La classe di base \"{name}\" è un TypedDict closed; elementi aggiuntivi non consentiti",
|
||||
"typedDictDelete": "Non è stato possibile eliminare l'elemento in TypedDict",
|
||||
"typedDictEmptyName": "I nomi all'interno di un TypedDict non possono essere vuoti",
|
||||
|
|
@ -605,6 +606,7 @@
|
|||
"unannotatedFunctionSkipped": "L'analisi della funzione \"{name}\" è stata ignorata perché non è annotata",
|
||||
"unaryOperationNotAllowed": "Operatore unario non consentito nell'espressione di tipo",
|
||||
"unexpectedAsyncToken": "È previsto che \"def\", \"with\" o \"for\" seguano \"async\"",
|
||||
"unexpectedEof": "Unexpected EOF",
|
||||
"unexpectedExprToken": "Token imprevisto alla fine dell'espressione",
|
||||
"unexpectedIndent": "Rientro imprevisto",
|
||||
"unexpectedUnindent": "Riduci rientro non previsto",
|
||||
|
|
@ -741,7 +743,7 @@
|
|||
"namedTupleNotAllowed": "Non è possibile usare NamedTuple per i controlli di istanze o classi",
|
||||
"newMethodLocation": "Il metodo __new__ è definito nella classe \"{type}\"",
|
||||
"newMethodSignature": "La firma del __new__ è \"{type}\"",
|
||||
"newTypeClassNotAllowed": "Impossibile utilizzare la classe creata con NewType con controlli di classe e di istanza",
|
||||
"newTypeClassNotAllowed": "Type created with NewType cannot be used with instance and class checks",
|
||||
"noOverloadAssignable": "Nessuna funzione di overload corrisponde al tipo \"{type}\"",
|
||||
"noneNotAllowed": "Non è possibile usare None per i controlli di istanze o classi",
|
||||
"orPatternMissingName": "Nomi mancanti: {name}",
|
||||
|
|
|
|||
|
|
@ -580,6 +580,7 @@
|
|||
"typedDictBaseClass": "TypedDict クラスのすべての基底クラスも TypedDict クラスである必要があります",
|
||||
"typedDictBoolParam": "\"{name}\" パラメーターの値は True または False である必要があります",
|
||||
"typedDictClosedExtras": "基底クラス \"{name}\" は、余分な項目の型を型 \"{type}\" に制限する TypedDict です",
|
||||
"typedDictClosedFalseNonOpenBase": "Base class \"{name}\" is not an open TypedDict; closed=False is not allowed",
|
||||
"typedDictClosedNoExtras": "基底クラス \"{name}\" は closed した TypedDict です。追加の項目は許可されていません",
|
||||
"typedDictDelete": "TypedDict の項目を削除できませんでした",
|
||||
"typedDictEmptyName": "TypedDict 内の名前を空にすることはできません",
|
||||
|
|
@ -605,6 +606,7 @@
|
|||
"unannotatedFunctionSkipped": "関数 \"{name}\" の分析は、表示されないためスキップされます",
|
||||
"unaryOperationNotAllowed": "単項演算子は型式では使用できません",
|
||||
"unexpectedAsyncToken": "\"def\"、\"with\"、または \"for\" が \"async\" の後に続く必要があります",
|
||||
"unexpectedEof": "Unexpected EOF",
|
||||
"unexpectedExprToken": "式の最後に予期しないトークンが含まれています",
|
||||
"unexpectedIndent": "予期しないインデント",
|
||||
"unexpectedUnindent": "インデント解除は予期されていません",
|
||||
|
|
@ -741,7 +743,7 @@
|
|||
"namedTupleNotAllowed": "NamedTuple はインスタンスまたはクラスのチェックには使用できません",
|
||||
"newMethodLocation": "__new__ メソッドはクラス \"{type}\" で定義されています",
|
||||
"newMethodSignature": "__new__の署名は \"{type}\" です",
|
||||
"newTypeClassNotAllowed": "NewType で作成されたクラスは、インスタンスおよびクラスのチェックでは使用できません",
|
||||
"newTypeClassNotAllowed": "Type created with NewType cannot be used with instance and class checks",
|
||||
"noOverloadAssignable": "型 \"{type}\" に一致するオーバーロードされた関数はありません",
|
||||
"noneNotAllowed": "インスタンスまたはクラスのチェックには None 使用できません",
|
||||
"orPatternMissingName": "名前がありません: {name}",
|
||||
|
|
|
|||
|
|
@ -580,6 +580,7 @@
|
|||
"typedDictBaseClass": "TypedDict 클래스의 모든 기본 클래스도 TypedDict 클래스여야 합니다.",
|
||||
"typedDictBoolParam": "\"{name}\" 매개 변수에 True 또는 False 값이 있어야 합니다.",
|
||||
"typedDictClosedExtras": "기본 클래스 \"{name}\" 추가 항목의 유형을 \"{type}\" 형식으로 제한하는 TypedDict.",
|
||||
"typedDictClosedFalseNonOpenBase": "Base class \"{name}\" is not an open TypedDict; closed=False is not allowed",
|
||||
"typedDictClosedNoExtras": "기본 클래스 \"{name}\"은(는) closed TypedDict입니다. 추가 항목은 허용되지 않습니다.",
|
||||
"typedDictDelete": "TypedDict에서 항목을 삭제할 수 없습니다.",
|
||||
"typedDictEmptyName": "TypedDict 내의 이름은 비워 둘 수 없습니다.",
|
||||
|
|
@ -605,6 +606,7 @@
|
|||
"unannotatedFunctionSkipped": "주석이 없으므로 ‘{name}’ 함수 분석을 건너뜁니다.",
|
||||
"unaryOperationNotAllowed": "단항 연산자는 형식 식에 사용할 수 없습니다.",
|
||||
"unexpectedAsyncToken": "\"async\"를 따르려면 \"def\", \"with\" 또는 \"for\"가 필요합니다.",
|
||||
"unexpectedEof": "Unexpected EOF",
|
||||
"unexpectedExprToken": "식 끝에 예기치 않은 토큰이 있습니다.",
|
||||
"unexpectedIndent": "예기치 않은 들여쓰기",
|
||||
"unexpectedUnindent": "들여쓰기가 필요 없음",
|
||||
|
|
@ -741,7 +743,7 @@
|
|||
"namedTupleNotAllowed": "인스턴스 또는 클래스 검사에는 NamedTuple을 사용할 수 없습니다.",
|
||||
"newMethodLocation": "__new__ 메서드가 \"{type}\" 클래스에 정의되어 있습니다.",
|
||||
"newMethodSignature": "__new__ 의 서명은 \"{type}\"입니다.",
|
||||
"newTypeClassNotAllowed": "NewType으로 만든 클래스는 인스턴스 및 클래스 검사에 사용할 수 없습니다.",
|
||||
"newTypeClassNotAllowed": "Type created with NewType cannot be used with instance and class checks",
|
||||
"noOverloadAssignable": "\"{type}\" 형식과 일치하는 오버로드된 함수가 없습니다.",
|
||||
"noneNotAllowed": "인스턴스 또는 클래스 검사에는 None을 사용할 수 없음",
|
||||
"orPatternMissingName": "누락된 이름: {name}",
|
||||
|
|
|
|||
|
|
@ -580,6 +580,7 @@
|
|||
"typedDictBaseClass": "Wszystkie klasy bazowe dla klas TypedDict muszą być również klasami TypedDict",
|
||||
"typedDictBoolParam": "Oczekiwano, że parametr „{name}” będzie miał wartość True lub False",
|
||||
"typedDictClosedExtras": "\"{name}\" klasy bazowej to TypedDict ograniczająca typ dodatkowych elementów do typu \"{type}\"",
|
||||
"typedDictClosedFalseNonOpenBase": "Base class \"{name}\" is not an open TypedDict; closed=False is not allowed",
|
||||
"typedDictClosedNoExtras": "Klasa bazowa „{name}” jest closed TypedDict; dodatkowe elementy są niedozwolone",
|
||||
"typedDictDelete": "Nie można usunąć elementu w typie TypedDict",
|
||||
"typedDictEmptyName": "Nazwy w elemencie TypedDict nie mogą być puste",
|
||||
|
|
@ -605,6 +606,7 @@
|
|||
"unannotatedFunctionSkipped": "Analiza funkcji „{name}” została pominięta, ponieważ nie ma adnotacji",
|
||||
"unaryOperationNotAllowed": "Operator jednoargumentowy nie jest dozwolony w wyrażeniu typu",
|
||||
"unexpectedAsyncToken": "Oczekiwano wartości „def”, „with” lub „for” po „async”",
|
||||
"unexpectedEof": "Unexpected EOF",
|
||||
"unexpectedExprToken": "Nieoczekiwany token na końcu wyrażenia",
|
||||
"unexpectedIndent": "Nieoczekiwane wcięcie",
|
||||
"unexpectedUnindent": "Nieoczekiwany brak wcięcia",
|
||||
|
|
@ -741,7 +743,7 @@
|
|||
"namedTupleNotAllowed": "Funkcja NamedTuple nie może być używana do sprawdzania wystąpień lub klas",
|
||||
"newMethodLocation": "Metoda __new__ jest zdefiniowana w klasie „{type}”",
|
||||
"newMethodSignature": "Sygnatura __new__ to typ „{type}”",
|
||||
"newTypeClassNotAllowed": "Klasy utworzonej za pomocą elementu NewType nie można używać z sprawdzaniem wystąpień i klas",
|
||||
"newTypeClassNotAllowed": "Type created with NewType cannot be used with instance and class checks",
|
||||
"noOverloadAssignable": "Żadna przeciążona funkcja nie pasuje do typu „{type}”",
|
||||
"noneNotAllowed": "Wartość None nie może być używana w przypadku kontroli wystąpień lub klas",
|
||||
"orPatternMissingName": "Brak nazw: {name}",
|
||||
|
|
|
|||
|
|
@ -580,6 +580,7 @@
|
|||
"typedDictBaseClass": "Todas as classes base para classes TypedDict também devem ser classes TypedDict",
|
||||
"typedDictBoolParam": "Esperava-se que o parâmetro \"{name}\" tivesse um valor True ou False",
|
||||
"typedDictClosedExtras": "A classe \"{name}\" é um TypedDict que limita o tipo de itens extras a serem digitados \"{type}\"",
|
||||
"typedDictClosedFalseNonOpenBase": "Base class \"{name}\" is not an open TypedDict; closed=False is not allowed",
|
||||
"typedDictClosedNoExtras": "A classe base \"{name}\" é um TypedDict closed; itens extras não são permitidos",
|
||||
"typedDictDelete": "Não foi possível excluir o item em TypedDict",
|
||||
"typedDictEmptyName": "Os nomes dentro de um TypedDict não podem estar vazios",
|
||||
|
|
@ -605,6 +606,7 @@
|
|||
"unannotatedFunctionSkipped": "A análise da função \"{name}\" foi ignorada porque não foi anotada",
|
||||
"unaryOperationNotAllowed": "Operador unário não permitido na expressão de tipo",
|
||||
"unexpectedAsyncToken": "Esperado \"def\", \"with\" ou \"for\" para acompanhar \"async\"",
|
||||
"unexpectedEof": "Unexpected EOF",
|
||||
"unexpectedExprToken": "Token inesperado no final da expressão",
|
||||
"unexpectedIndent": "Recuo inesperado",
|
||||
"unexpectedUnindent": "Recuo não esperado",
|
||||
|
|
@ -741,7 +743,7 @@
|
|||
"namedTupleNotAllowed": "NamedTuple não pode ser usado para verificações de instância ou de classe",
|
||||
"newMethodLocation": "O método __new__ é definido na classe \"{type}\"",
|
||||
"newMethodSignature": "A assinatura de__new__ é \"{type}\"",
|
||||
"newTypeClassNotAllowed": "A classe criada com NewType não pode ser usada com verificações de instância e classe",
|
||||
"newTypeClassNotAllowed": "Type created with NewType cannot be used with instance and class checks",
|
||||
"noOverloadAssignable": "Nenhuma função sobrecarregada corresponde ao tipo \"{type}\"",
|
||||
"noneNotAllowed": "None não pode ser usado para verificações de instância ou de classe",
|
||||
"orPatternMissingName": "Nomes ausentes: {name}",
|
||||
|
|
|
|||
|
|
@ -580,6 +580,7 @@
|
|||
"typedDictBaseClass": "[HxyA2][นั้Æll þæsë çlæssës før TypedDict çlæssës mµst ælsø þë TypedDict çlæssësẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृまนั้ढूँ]",
|
||||
"typedDictBoolParam": "[GALOD][นั้Ëxpëçtëð \"{ñæmë}\" pæræmëtër tø hævë æ vælµë øf True ør FalseẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्นั้ढूँ]",
|
||||
"typedDictClosedExtras": "[mlkJO][นั้ßæsë çlæss \"{ñæmë}\" ïs æ TypedDict thæt lïmïts thë tÿpë øf ëxtræ ïtëms tø tÿpë \"{tÿpë}\"Ấğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्นั้ढूँ]",
|
||||
"typedDictClosedFalseNonOpenBase": "[ifIlm][นั้ßæsë çlæss \"{ñæmë}\" ïs ñøt æñ øpëñ TypedDict; closed=Fælsë ïs ñøt ælløwëðẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृまẤนั้ढूँ]",
|
||||
"typedDictClosedNoExtras": "[BCyXd][นั้ßæsë çlæss \"{ñæmë}\" ïs æ closed TypedDict; ëxtræ ïtëms ærë ñøt ælløwëðẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृまนั้ढूँ]",
|
||||
"typedDictDelete": "[bdBu7][นั้Çøµlð ñøt ðëlëtë ïtëm ïñ TypedDictẤğ倪İЂҰक्र्तिृまนั้ढूँ]",
|
||||
"typedDictEmptyName": "[h45e7][นั้Ñæmës wïthïñ æ TypedDict çæññøt þë ëmptÿẤğ倪İЂҰक्र्तिृまẤğนั้ढूँ]",
|
||||
|
|
@ -605,6 +606,7 @@
|
|||
"unannotatedFunctionSkipped": "[Ovgyl][นั้Æñælÿsïs øf fµñçtïøñ \"{ñæmë}\" ïs skïppëð þëçæµsë ït ïs µñæññøtætëðẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृนั้ढूँ]",
|
||||
"unaryOperationNotAllowed": "[2WB31][นั้Üñærÿ øpërætør ñøt ælløwëð ïñ tÿpë ëxprëssïøñẤğ倪İЂҰक्र्तिृまẤğ倪İนั้ढूँ]",
|
||||
"unexpectedAsyncToken": "[fKSJb][นั้Ëxpëçtëð \"def\", \"with\" ør \"for\" tø følløw \"async\"Ấğ倪İЂҰक्र्तिृまẤğ倪İЂҰนั้ढूँ]",
|
||||
"unexpectedEof": "[SyST0][นั้Üñëxpëçtëð ËØFẤğ倪İЂҰนั้ढूँ]",
|
||||
"unexpectedExprToken": "[MtBsu][นั้Üñëxpëçtëð tøkëñ æt ëñð øf ëxprëssïøñẤğ倪İЂҰक्र्तिृまẤนั้ढूँ]",
|
||||
"unexpectedIndent": "[uZUVS][นั้Üñëxpëçtëð ïñðëñtætïøñẤğ倪İЂҰक्र्นั้ढूँ]",
|
||||
"unexpectedUnindent": "[yqwy4][นั้Üñïñðëñt ñøt ëxpëçtëðẤğ倪İЂҰक्นั้ढूँ]",
|
||||
|
|
@ -741,7 +743,7 @@
|
|||
"namedTupleNotAllowed": "[gAlSp][นั้NamedTuple çæññøt þë µsëð før ïñstæñçë ør çlæss çhëçksẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्นั้ढूँ]",
|
||||
"newMethodLocation": "[n0dxL][นั้Thë __new__ mëthøð ïs ðëfïñëð ïñ çlæss \"{tÿpë}\"Ấğ倪İЂҰक्र्तिृまẤğ倪İЂนั้ढूँ]",
|
||||
"newMethodSignature": "[NeWKO][นั้§ïgñætµrë øf __new__ ïs \"{tÿpë}\"Ấğ倪İЂҰक्र्तिृนั้ढूँ]",
|
||||
"newTypeClassNotAllowed": "[JQmcY][นั้Çlæss çrëætëð wïth NewType çæññøt þë µsëð wïth ïñstæñçë æñð çlæss çhëçksẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृまẤนั้ढूँ]",
|
||||
"newTypeClassNotAllowed": "[JQmcY][นั้Tÿpë çrëætëð wïth NewType çæññøt þë µsëð wïth ïñstæñçë æñð çlæss çhëçksẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृまนั้ढूँ]",
|
||||
"noOverloadAssignable": "[FJ88c][นั้Ñø øvërløæðëð fµñçtïøñ mætçhës tÿpë \"{tÿpë}\"Ấğ倪İЂҰक्र्तिृまẤğ倪İนั้ढूँ]",
|
||||
"noneNotAllowed": "[Yn8Lx][นั้None çæññøt þë µsëð før ïñstæñçë ør çlæss çhëçksẤğ倪İЂҰक्र्तिृまẤğ倪İЂนั้ढूँ]",
|
||||
"orPatternMissingName": "[kgiPM][นั้Mïssïñg ñæmës: {ñæmë}Ấğ倪İЂҰक्นั้ढूँ]",
|
||||
|
|
|
|||
|
|
@ -580,6 +580,7 @@
|
|||
"typedDictBaseClass": "Все базовые классы для классов TypedDict также должны быть классами TypedDict",
|
||||
"typedDictBoolParam": "От параметра \"{name}\" ожидается значение True или False",
|
||||
"typedDictClosedExtras": "Базовый класс \"{name}\" является TypedDict, который ограничивает тип дополнительных элементов типом \"{type}\"",
|
||||
"typedDictClosedFalseNonOpenBase": "Base class \"{name}\" is not an open TypedDict; closed=False is not allowed",
|
||||
"typedDictClosedNoExtras": "Базовый класс \"{name}\" представляет собой closed TypedDict; дополнительные элементы не разрешены",
|
||||
"typedDictDelete": "Не удалось удалить элемент в TypedDict",
|
||||
"typedDictEmptyName": "Имена в TypedDict не могут быть пустыми",
|
||||
|
|
@ -605,6 +606,7 @@
|
|||
"unannotatedFunctionSkipped": "Анализ функции \"{name}\" пропущен, так как она не аннотирована.",
|
||||
"unaryOperationNotAllowed": "Унарный оператор нельзя использовать в выражении типа",
|
||||
"unexpectedAsyncToken": "После \"async\" ожидается \"def\", \"with\" или \"for\"",
|
||||
"unexpectedEof": "Unexpected EOF",
|
||||
"unexpectedExprToken": "Непредвиденный токен в конце выражения",
|
||||
"unexpectedIndent": "Непредвиденный отступ",
|
||||
"unexpectedUnindent": "Отступ не ожидается",
|
||||
|
|
@ -741,7 +743,7 @@
|
|||
"namedTupleNotAllowed": "NamedTuple не может использоваться для проверок экземпляров или классов",
|
||||
"newMethodLocation": "Метод __new__ определен в классе \"{type}\"",
|
||||
"newMethodSignature": "Сигнатура метода __new__ требует \"{type}\"",
|
||||
"newTypeClassNotAllowed": "Класс, созданный с NewType, нельзя использовать с проверками экземпляров и классов",
|
||||
"newTypeClassNotAllowed": "Type created with NewType cannot be used with instance and class checks",
|
||||
"noOverloadAssignable": "Нет перегруженной функции, соответствующей типу \"{type}\"",
|
||||
"noneNotAllowed": "None невозможно использовать для проверок экземпляров или классов",
|
||||
"orPatternMissingName": "Отсутствуют имена: {name}",
|
||||
|
|
|
|||
|
|
@ -580,6 +580,7 @@
|
|||
"typedDictBaseClass": "TypedDict sınıfları için tüm temel sınıflar da TypedDict sınıfları olmalıdır",
|
||||
"typedDictBoolParam": "True veya False değeri olması için \"{name}\" parametresi bekleniyordu",
|
||||
"typedDictClosedExtras": "Temel sınıf \"{name}\", TypedDict öğe türünü türle sınırlanmış bir \"{type}\"",
|
||||
"typedDictClosedFalseNonOpenBase": "Base class \"{name}\" is not an open TypedDict; closed=False is not allowed",
|
||||
"typedDictClosedNoExtras": "\"{name}\" temel sınıfı closed bir TypedDict öğesidir; ek öğelere izin verilmiyor",
|
||||
"typedDictDelete": "TypedDict'da öğe silinemedi",
|
||||
"typedDictEmptyName": "TypedDict içindeki adlar boş olamaz",
|
||||
|
|
@ -605,6 +606,7 @@
|
|||
"unannotatedFunctionSkipped": "\"{name}\" işlevinin analizi, açıklanmadığından atlandı",
|
||||
"unaryOperationNotAllowed": "Tür ifadesinde birli işleç kullanılamaz",
|
||||
"unexpectedAsyncToken": "\"async\" öğesinin ardından \"def\", \"with\" veya \"for\" bekleniyordu",
|
||||
"unexpectedEof": "Unexpected EOF",
|
||||
"unexpectedExprToken": "İfadenin sonunda beklenmeyen belirteç",
|
||||
"unexpectedIndent": "Beklenmeyen girinti",
|
||||
"unexpectedUnindent": "Girintiyi kaldırma beklenmiyordu",
|
||||
|
|
@ -741,7 +743,7 @@
|
|||
"namedTupleNotAllowed": "NamedTuple örnek veya sınıf kontrolleri için kullanılamaz",
|
||||
"newMethodLocation": "\"{type}\" sınıfı içinde __new__ metodu tanımlandı",
|
||||
"newMethodSignature": "__new__ imzası \"{type}\"",
|
||||
"newTypeClassNotAllowed": "NewType ile oluşturulan sınıf, örnek ve sınıf denetimleriyle kullanılamaz",
|
||||
"newTypeClassNotAllowed": "Type created with NewType cannot be used with instance and class checks",
|
||||
"noOverloadAssignable": "Aşırı yüklenmiş işlevlerden hiçbiri \"{type}\" türüyle uyuşmuyor",
|
||||
"noneNotAllowed": "Örnek veya sınıf denetimleri için None kullanılamaz",
|
||||
"orPatternMissingName": "Eksik adlar: {name}",
|
||||
|
|
|
|||
|
|
@ -580,6 +580,7 @@
|
|||
"typedDictBaseClass": "TypedDict 类的所有基类也必须是 TypedDict 类",
|
||||
"typedDictBoolParam": "预期“{name}”参数的值为 True 或 False",
|
||||
"typedDictClosedExtras": "基类 \"{name}\" 是限制额外项类型 \"{type}\" 的 TypedDict",
|
||||
"typedDictClosedFalseNonOpenBase": "Base class \"{name}\" is not an open TypedDict; closed=False is not allowed",
|
||||
"typedDictClosedNoExtras": "基类 \"{name}\" 是 closed TypedDict; 不允许使用额外的项",
|
||||
"typedDictDelete": "无法删除 TypedDict 中的项",
|
||||
"typedDictEmptyName": "TypedDict 中的名称不能为空",
|
||||
|
|
@ -605,6 +606,7 @@
|
|||
"unannotatedFunctionSkipped": "已跳过对函数“{name}”的分析,因为它未被批注",
|
||||
"unaryOperationNotAllowed": "类型表达式中不允许使用一元运算符",
|
||||
"unexpectedAsyncToken": "“def”、“with” 或 “for” 应跟随 “async”",
|
||||
"unexpectedEof": "Unexpected EOF",
|
||||
"unexpectedExprToken": "表达式末尾出现意外标记",
|
||||
"unexpectedIndent": "意外缩进",
|
||||
"unexpectedUnindent": "不应取消缩进",
|
||||
|
|
@ -741,7 +743,7 @@
|
|||
"namedTupleNotAllowed": "不能对实例或类检查使用 NamedTuple",
|
||||
"newMethodLocation": "__new__方法已在类“{type}”中定义",
|
||||
"newMethodSignature": "__new__的签名为“{type}”",
|
||||
"newTypeClassNotAllowed": "不能将使用 NewType 创建的类用于实例和类检查",
|
||||
"newTypeClassNotAllowed": "Type created with NewType cannot be used with instance and class checks",
|
||||
"noOverloadAssignable": "没有重载函数与类型“{type}”匹配",
|
||||
"noneNotAllowed": "不能对实例或类检查使用 None",
|
||||
"orPatternMissingName": "缺少名称: {name}",
|
||||
|
|
|
|||
|
|
@ -580,6 +580,7 @@
|
|||
"typedDictBaseClass": "TypedDict 類別的所有基底類別也必須是 TypedDict 類別",
|
||||
"typedDictBoolParam": "預期 \"{name}\" 參數的值為 True 或 False",
|
||||
"typedDictClosedExtras": "基類 \"{name}\" 是限制額外專案類型的 TypedDict \"{type}\"",
|
||||
"typedDictClosedFalseNonOpenBase": "Base class \"{name}\" is not an open TypedDict; closed=False is not allowed",
|
||||
"typedDictClosedNoExtras": "基底類別 \"{name}\" 是 closed 的 TypedDict; 不允許額外項目",
|
||||
"typedDictDelete": "無法刪除 TypedDict 中的項目",
|
||||
"typedDictEmptyName": "TypedDict 內的名稱不可為空白",
|
||||
|
|
@ -605,6 +606,7 @@
|
|||
"unannotatedFunctionSkipped": "因為未標註函式 \"{name}\",所以略過其分析",
|
||||
"unaryOperationNotAllowed": "類型運算式中不允許一元運算子",
|
||||
"unexpectedAsyncToken": "預期為 \"def\"、\"with\" 或 \"for\" 來追蹤 \"async\"",
|
||||
"unexpectedEof": "Unexpected EOF",
|
||||
"unexpectedExprToken": "運算式結尾未預期的權杖",
|
||||
"unexpectedIndent": "未預期的縮排",
|
||||
"unexpectedUnindent": "取消縮排未預期",
|
||||
|
|
@ -741,7 +743,7 @@
|
|||
"namedTupleNotAllowed": "執行個體或類別檢查無法使用 NamedTuple",
|
||||
"newMethodLocation": "__new__ 方法於類別 \"{type}\" 中定義",
|
||||
"newMethodSignature": "__new__ 的簽章為 \"{type}\"",
|
||||
"newTypeClassNotAllowed": "使用 NewType 建立的類別不能與執行個體和類別檢查一起使用",
|
||||
"newTypeClassNotAllowed": "Type created with NewType cannot be used with instance and class checks",
|
||||
"noOverloadAssignable": "沒有任何多載函式符合類型 \"{type}\"",
|
||||
"noneNotAllowed": "無法對執行個體或類別檢查使用 None",
|
||||
"orPatternMissingName": "遺失名稱: {name}",
|
||||
|
|
|
|||
|
|
@ -420,6 +420,7 @@ async function processArgs(): Promise<ExitStatus> {
|
|||
hostFactory: () => new FullAccessHost(serviceProvider),
|
||||
// Refresh service 2 seconds after the last library file change is detected.
|
||||
libraryReanalysisTimeProvider: () => 2 * 1000,
|
||||
shouldRunAnalysis: () => true,
|
||||
});
|
||||
|
||||
if ('threads' in args) {
|
||||
|
|
@ -792,6 +793,7 @@ function runWorkerMessageLoop(workerNum: number, tempFolderName: string) {
|
|||
hostFactory: () => new FullAccessHost(serviceProvider!),
|
||||
// Refresh service 2 seconds after the last library file change is detected.
|
||||
libraryReanalysisTimeProvider: () => 2 * 1000,
|
||||
shouldRunAnalysis: () => true,
|
||||
});
|
||||
|
||||
service.setCompletionCallback((results) => {
|
||||
|
|
|
|||
|
|
@ -269,6 +269,7 @@ function createServiceWithChainedSourceFiles(basePath: Uri, code: string) {
|
|||
importResolverFactory: AnalyzerService.createImportResolver,
|
||||
configOptions: new ConfigOptions(basePath),
|
||||
fileSystem: fs,
|
||||
shouldRunAnalysis: () => true,
|
||||
});
|
||||
|
||||
const data = parseTestData(basePath.getFilePath(), code, '');
|
||||
|
|
|
|||
|
|
@ -607,6 +607,10 @@ describe(`config test'}`, () => {
|
|||
const serviceProvider = createServiceProvider(fs, cons, tempFile);
|
||||
const host = new TestAccessHost();
|
||||
host.getPythonVersion = () => pythonVersion3_13;
|
||||
return new AnalyzerService('<default>', serviceProvider, { console: cons, hostFactory: () => host });
|
||||
return new AnalyzerService('<default>', serviceProvider, {
|
||||
console: cons,
|
||||
hostFactory: () => host,
|
||||
shouldRunAnalysis: () => true,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -216,6 +216,7 @@ function createWorkspace(rootUri: Uri | undefined) {
|
|||
hostFactory: () => new TestAccessHost(),
|
||||
importResolverFactory: AnalyzerService.createImportResolver,
|
||||
configOptions: new ConfigOptions(Uri.empty()),
|
||||
shouldRunAnalysis: () => true,
|
||||
}),
|
||||
disableLanguageServices: false,
|
||||
disableTaggedHints: false,
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ export class TestLanguageService implements LanguageServerInterface {
|
|||
importResolverFactory: AnalyzerService.createImportResolver,
|
||||
configOptions: new ConfigOptions(Uri.empty()),
|
||||
fileSystem: this.fs,
|
||||
shouldRunAnalysis: () => true,
|
||||
}
|
||||
),
|
||||
disableLanguageServices: false,
|
||||
|
|
|
|||
|
|
@ -1732,6 +1732,7 @@ export class TestState {
|
|||
configOptions,
|
||||
fileSystem: this.fs,
|
||||
libraryReanalysisTimeProvider: () => 0,
|
||||
shouldRunAnalysis: () => true,
|
||||
});
|
||||
|
||||
// directly set files to track rather than using fileSpec from config
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import {
|
|||
PyrightServerInfo,
|
||||
runPyrightServer,
|
||||
waitForDiagnostics,
|
||||
waitForPushDiagnostics,
|
||||
} from './lsp/languageServerTestUtils';
|
||||
|
||||
describe(`Basic language server tests`, () => {
|
||||
|
|
@ -155,7 +156,7 @@ describe(`Basic language server tests`, () => {
|
|||
describe(`Diagnostics ${supportsPullDiagnostics ? 'pull' : 'push'}`, () => {
|
||||
// Background analysis takes longer than 5 seconds sometimes, so we need to
|
||||
// increase the timeout.
|
||||
jest.setTimeout(15000);
|
||||
jest.setTimeout(20000);
|
||||
test('background thread diagnostics', async () => {
|
||||
const code = `
|
||||
// @filename: root/test.py
|
||||
|
|
@ -190,7 +191,7 @@ describe(`Basic language server tests`, () => {
|
|||
await openFile(info, 'marker');
|
||||
|
||||
// Wait for the diagnostics to publish
|
||||
const diagnostics = await waitForDiagnostics(info);
|
||||
const diagnostics = await waitForPushDiagnostics(info, false);
|
||||
const diagnostic = diagnostics.find((d) => d.uri.includes('root/test.py'));
|
||||
assert(diagnostic);
|
||||
assert.equal(diagnostic.diagnostics.length, 6);
|
||||
|
|
@ -237,12 +238,8 @@ describe(`Basic language server tests`, () => {
|
|||
const diagnostics = await waitForDiagnostics(info);
|
||||
const diagnostic = diagnostics.find((d) => d.uri.includes('root/test.py'));
|
||||
assert(diagnostic);
|
||||
assert.equal(diagnostic.diagnostics.length, 6);
|
||||
|
||||
// Make sure the error has a special rule
|
||||
assert.equal(diagnostic.diagnostics[1].code, 'reportUnusedImport');
|
||||
assert.equal(diagnostic.diagnostics[3].code, 'reportUnusedImport');
|
||||
assert.equal(diagnostic.diagnostics[4].code, 'reportUnusedImport');
|
||||
const unusedImports = diagnostic.diagnostics.filter((d) => d.code === 'reportUnusedImport');
|
||||
assert.equal(unusedImports.length, 3);
|
||||
});
|
||||
|
||||
test('Diagnostic severity overrides test', async () => {
|
||||
|
|
|
|||
|
|
@ -116,6 +116,8 @@ export interface PyrightServerInfo {
|
|||
getInitializeParams(): InitializeParams;
|
||||
dispose(): Promise<void>;
|
||||
convertPathToUri(path: string): Uri;
|
||||
workspaceDiagnosticsPartialResultToken?: string;
|
||||
pendingWorkspaceDiagnostics?: Promise<any>;
|
||||
}
|
||||
|
||||
export class TestHostOptions {
|
||||
|
|
@ -288,20 +290,53 @@ export async function getOpenFiles(info: PyrightServerInfo, projectRoot?: Uri):
|
|||
return deserialize(result.files);
|
||||
}
|
||||
|
||||
async function waitForPushDiagnostics(info: PyrightServerInfo, timeout = 10000) {
|
||||
const deferred = createDeferred<void>();
|
||||
const disposable = info.diagnosticsEvent((params) => {
|
||||
if (params.diagnostics.length > 0) {
|
||||
deferred.resolve();
|
||||
}
|
||||
});
|
||||
const timer = setTimeout(() => deferred.reject('Timed out waiting for diagnostics'), timeout);
|
||||
try {
|
||||
await deferred.promise;
|
||||
} finally {
|
||||
clearTimeout(timer);
|
||||
disposable.dispose();
|
||||
export async function waitForPushDiagnostics(
|
||||
info: PyrightServerInfo,
|
||||
clearFirst: boolean,
|
||||
numberOfFiles = 1,
|
||||
timeout = 10000
|
||||
): Promise<PublishDiagnosticsParams[]> {
|
||||
if (clearFirst) {
|
||||
info.diagnostics = [];
|
||||
}
|
||||
|
||||
// We may already have the necessary diagnostics.
|
||||
const currentCount = info.diagnostics.filter((d) => d.diagnostics.length > 0).length;
|
||||
if (currentCount >= numberOfFiles) {
|
||||
return info.diagnostics;
|
||||
}
|
||||
|
||||
// Otherwise we have to get called back with the diagnostics. Swallow any errors (timeouts, etc.)
|
||||
// and just return what we currently have so callers can choose how strict to be.
|
||||
let eventCount = currentCount;
|
||||
try {
|
||||
await waitForEvent(
|
||||
info.diagnosticsEvent,
|
||||
'diagnostics',
|
||||
(params) => {
|
||||
if (params.diagnostics.length > 0) {
|
||||
eventCount++;
|
||||
if (eventCount >= numberOfFiles) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
timeout
|
||||
);
|
||||
} catch (e: any) {
|
||||
try {
|
||||
console.log?.(
|
||||
`waitForPushDiagnostics: ignoring error while waiting for diagnostics: ${
|
||||
e?.message || e
|
||||
}. Had ${eventCount} of ${numberOfFiles} events`
|
||||
);
|
||||
} catch {
|
||||
/* ignore logging issues */
|
||||
}
|
||||
}
|
||||
|
||||
return info.diagnostics;
|
||||
}
|
||||
|
||||
|
|
@ -354,11 +389,7 @@ export function convertDiagnosticReport(
|
|||
async function waitForPullDiagnostics(info: PyrightServerInfo): Promise<PublishDiagnosticsParams[]> {
|
||||
const openFiles = await getOpenFiles(info);
|
||||
if (openFiles.length <= 0) {
|
||||
const results = await info.connection.sendRequest(WorkspaceDiagnosticRequest.type, {
|
||||
identifier: 'Pylance',
|
||||
previousResultIds: [],
|
||||
});
|
||||
return convertDiagnosticReport(undefined, results);
|
||||
return waitForPushDiagnostics(info, false);
|
||||
} else {
|
||||
const results: PublishDiagnosticsParams[] = [];
|
||||
for (const openFile of openFiles) {
|
||||
|
|
@ -378,7 +409,7 @@ export async function waitForDiagnostics(info: PyrightServerInfo, timeout = 2000
|
|||
// Timeout doesn't apply on pull because we can actually ask for them.
|
||||
return waitForPullDiagnostics(info);
|
||||
}
|
||||
return waitForPushDiagnostics(info, timeout);
|
||||
return waitForPushDiagnostics(info, false, undefined, timeout);
|
||||
}
|
||||
|
||||
interface ProgressPart {}
|
||||
|
|
@ -419,6 +450,24 @@ class TestProgressPart implements ProgressPart {
|
|||
}
|
||||
}
|
||||
|
||||
export async function waitForPromise(promise: Promise<any>, timeout = 10000, message?: string): Promise<any> {
|
||||
return await new Promise((resolve, reject) => {
|
||||
const timer = setTimeout(() => {
|
||||
reject(new Error(message || `Timed out waiting for promise`));
|
||||
}, timeout);
|
||||
|
||||
promise
|
||||
.then((result) => {
|
||||
clearTimeout(timer);
|
||||
resolve(result);
|
||||
})
|
||||
.catch((error) => {
|
||||
clearTimeout(timer);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function runPyrightServer(
|
||||
projectRoots: string[] | string,
|
||||
code: string,
|
||||
|
|
@ -469,7 +518,7 @@ export async function runPyrightServer(
|
|||
const serverStarted = createDeferred<string>();
|
||||
const diagnosticsEmitter = new Emitter<PublishDiagnosticsParams>();
|
||||
const workspaceEditsEmitter = new Emitter<ApplyWorkspaceEditParams>();
|
||||
const diagnosticsMode = extraSettings?.find((s) => s.item.section === 'python.analysis')?.value?.diagnosticMode;
|
||||
const partialResultToken = `4fb5ab8a-37a6-4c16-a290-03cfc892ea7e`; // Doesn't need to be different, just a random guid
|
||||
|
||||
// Setup the server info.
|
||||
const info: PyrightServerInfo = {
|
||||
|
|
@ -484,26 +533,28 @@ export async function runPyrightServer(
|
|||
testData,
|
||||
testName: testServerData.testName,
|
||||
telemetry: [],
|
||||
supportsPullDiagnostics: (supportPullDiagnostics && diagnosticsMode !== 'workspace') ?? false,
|
||||
supportsPullDiagnostics: !!supportPullDiagnostics,
|
||||
projectRoots: testServerData.projectRoots,
|
||||
diagnostics: [],
|
||||
diagnosticsEvent: diagnosticsEmitter.event,
|
||||
workspaceEdits: [],
|
||||
workspaceEditsEvent: workspaceEditsEmitter.event,
|
||||
getInitializeParams: () =>
|
||||
getInitializeParams(testServerData.projectRoots, !!supportPullDiagnostics, diagnosticsMode),
|
||||
getInitializeParams: () => getInitializeParams(testServerData.projectRoots, !!supportPullDiagnostics),
|
||||
convertPathToUri: (path: string) => UriEx.file(path, !ignoreCase),
|
||||
dispose: async () => {
|
||||
// Send shutdown. This should disconnect the dispatcher and kill the server.
|
||||
if (serverWorker) {
|
||||
await connection.sendRequest(ShutdownRequest.type, undefined);
|
||||
}
|
||||
// Shutdown of the server should resolve any pending workspace diagnostics requests.
|
||||
await stopWorkspaceDiagnostics(info, 'shutdown');
|
||||
|
||||
// Now we can dispose the connection.
|
||||
disposables.forEach((d) => d.dispose());
|
||||
|
||||
logToDisk(`Finished test ${testServerData.testName}`, testServerData.logFile);
|
||||
},
|
||||
workspaceDiagnosticsPartialResultToken: supportPullDiagnostics ? partialResultToken : undefined,
|
||||
};
|
||||
info.disposables.push(
|
||||
info.connection.onNotification(CustomLSP.Notifications.TestStartServerResponse, (p) => {
|
||||
|
|
@ -511,6 +562,18 @@ export async function runPyrightServer(
|
|||
}),
|
||||
info.connection.onRequest(RegistrationRequest.type, (p) => {
|
||||
info.registrations.push(...p.registrations);
|
||||
|
||||
// If this is a DocumentDiagnostic registration, we may need to start workspace diagnostics.
|
||||
const documentDiagnosticRegistration = p.registrations.find(
|
||||
(r) => r.method === DocumentDiagnosticRequest.type.method
|
||||
);
|
||||
if (documentDiagnosticRegistration) {
|
||||
if (documentDiagnosticRegistration.registerOptions.workspaceDiagnostics) {
|
||||
startWorkspaceDiagnostics(info, 'registration');
|
||||
} else {
|
||||
stopWorkspaceDiagnostics(info, 'registration');
|
||||
}
|
||||
}
|
||||
}),
|
||||
info.connection.onNotification(CustomLSP.Notifications.TestSignal, (p: CustomLSP.TestSignal) => {
|
||||
info.signals.get(p.kind)!.resolve(true);
|
||||
|
|
@ -558,6 +621,15 @@ export async function runPyrightServer(
|
|||
}),
|
||||
info.connection.onNotification(TelemetryEventNotification.type, (p) => {
|
||||
info.telemetry.push(p);
|
||||
}),
|
||||
info.connection.onProgress(WorkspaceDiagnosticRequest.partialResult, partialResultToken, (progress) => {
|
||||
const converted = convertDiagnosticReport(undefined, progress);
|
||||
// Replace any current diagnostics with their new set
|
||||
for (const p of converted) {
|
||||
info.diagnostics = info.diagnostics.filter((d) => d.uri !== p.uri);
|
||||
info.diagnostics.push(p);
|
||||
diagnosticsEmitter.fire(p);
|
||||
}
|
||||
})
|
||||
);
|
||||
info.disposables.push(
|
||||
|
|
@ -617,6 +689,37 @@ export async function runPyrightServer(
|
|||
return info;
|
||||
}
|
||||
|
||||
function startWorkspaceDiagnostics(info: PyrightServerInfo, extraMessage: string) {
|
||||
if (!info.pendingWorkspaceDiagnostics) {
|
||||
info.logs.push({ message: `Starting workspace diagnostics request: ${extraMessage}`, type: 4 });
|
||||
info.pendingWorkspaceDiagnostics = info.connection
|
||||
.sendRequest(WorkspaceDiagnosticRequest.type, {
|
||||
identifier: 'Pylance',
|
||||
previousResultIds: [],
|
||||
partialResultToken: info.workspaceDiagnosticsPartialResultToken,
|
||||
})
|
||||
.then(() => {
|
||||
info.logs.push({ message: 'Workspace diagnostics request completed', type: 4 });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function stopWorkspaceDiagnostics(info: PyrightServerInfo, extraMessage: string) {
|
||||
if (info.pendingWorkspaceDiagnostics) {
|
||||
const pending = info.pendingWorkspaceDiagnostics;
|
||||
info.pendingWorkspaceDiagnostics = undefined;
|
||||
try {
|
||||
await waitForPromise(
|
||||
pending,
|
||||
5000,
|
||||
`Timed out waiting for stopping workspace diagnostics during ${extraMessage}`
|
||||
);
|
||||
} catch {
|
||||
// Ignore errors. We're trying to stop it.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function initializeLanguageServer(info: PyrightServerInfo) {
|
||||
const params = info.getInitializeParams();
|
||||
|
||||
|
|
@ -640,6 +743,10 @@ export async function initializeLanguageServer(info: PyrightServerInfo) {
|
|||
await info.signals.get(CustomLSP.TestSignalKinds.Initialization)!.promise;
|
||||
}
|
||||
|
||||
// Start the polling for workspace diagnostics as done by the VS Code LSP client.
|
||||
if (result.capabilities.diagnosticProvider?.workspaceDiagnostics) {
|
||||
startWorkspaceDiagnostics(info, 'initialize');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -677,11 +784,7 @@ export async function hover(info: PyrightServerInfo, markerName: string) {
|
|||
return hoverResult;
|
||||
}
|
||||
|
||||
export function getInitializeParams(
|
||||
projectRoots: Uri[],
|
||||
supportsPullDiagnostics: boolean,
|
||||
diagnosticMode: string | undefined = undefined
|
||||
) {
|
||||
export function getInitializeParams(projectRoots: Uri[], supportsPullDiagnostics: boolean) {
|
||||
// cloned vscode "1.71.0-insider"'s initialize params.
|
||||
const workspaceFolders = projectRoots
|
||||
? projectRoots.map((root, i) => ({ name: root.fileName, uri: projectRoots[i].toString() }))
|
||||
|
|
@ -1034,7 +1137,6 @@ export function getInitializeParams(
|
|||
},
|
||||
initializationOptions: {
|
||||
autoFormatStrings: true,
|
||||
diagnosticMode: diagnosticMode ?? 'openFilesOnly',
|
||||
disablePullDiagnostics: !supportsPullDiagnostics,
|
||||
},
|
||||
workspaceFolders,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue